mirror of
https://github.com/TomHarte/CLK.git
synced 2025-08-09 20:25:19 +00:00
Added a very basic attempt at shadow mask emulation.
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
21
OSBindings/Mac/Clock Signal/Assets.xcassets/ShadowMask.imageset/Contents.json
vendored
Normal file
21
OSBindings/Mac/Clock Signal/Assets.xcassets/ShadowMask.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "ShadowMask.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
BIN
OSBindings/Mac/Clock Signal/Assets.xcassets/ShadowMask.imageset/ShadowMask.png
vendored
Normal file
BIN
OSBindings/Mac/Clock Signal/Assets.xcassets/ShadowMask.imageset/ShadowMask.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#import "CSCathodeRayView.h"
|
#import "CSCathodeRayView.h"
|
||||||
@import CoreVideo;
|
@import CoreVideo;
|
||||||
|
@import GLKit;
|
||||||
#import <OpenGL/gl3.h>
|
#import <OpenGL/gl3.h>
|
||||||
#import <OpenGL/gl3ext.h>
|
#import <OpenGL/gl3ext.h>
|
||||||
#import <libkern/OSAtomic.h>
|
#import <libkern/OSAtomic.h>
|
||||||
@@ -23,11 +24,10 @@
|
|||||||
GLint _textureCoordinatesAttribute;
|
GLint _textureCoordinatesAttribute;
|
||||||
GLint _lateralAttribute;
|
GLint _lateralAttribute;
|
||||||
|
|
||||||
GLint _texIDUniform;
|
GLint _textureSizeUniform, _windowSizeUniform;
|
||||||
GLint _textureSizeUniform;
|
|
||||||
GLint _alphaUniform;
|
GLint _alphaUniform;
|
||||||
|
|
||||||
GLuint _textureName;
|
GLuint _textureName, _shadowMaskTextureName;
|
||||||
CRTSize _textureSize;
|
CRTSize _textureSize;
|
||||||
|
|
||||||
CRTFrame *_crtFrame;
|
CRTFrame *_crtFrame;
|
||||||
@@ -37,6 +37,24 @@
|
|||||||
int32_t _compiledSignalDecoderGeneration;
|
int32_t _compiledSignalDecoderGeneration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (GLuint)textureForImageNamed:(NSString *)name
|
||||||
|
{
|
||||||
|
NSImage *const image = [NSImage imageNamed:name];
|
||||||
|
NSBitmapImageRep *bitmapRepresentation = [[NSBitmapImageRep alloc] initWithData: [image TIFFRepresentation]];
|
||||||
|
|
||||||
|
GLuint textureName;
|
||||||
|
glGenTextures(1, &textureName);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textureName);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei)image.size.width, (GLsizei)image.size.height, 0, GL_RGB, GL_UNSIGNED_BYTE, bitmapRepresentation.bitmapData);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
return textureName;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)prepareOpenGL
|
- (void)prepareOpenGL
|
||||||
{
|
{
|
||||||
// Synchronize buffer swaps with vertical refresh rate
|
// Synchronize buffer swaps with vertical refresh rate
|
||||||
@@ -54,6 +72,13 @@
|
|||||||
CGLPixelFormatObj cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj];
|
CGLPixelFormatObj cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj];
|
||||||
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, cglContext, cglPixelFormat);
|
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, cglContext, cglPixelFormat);
|
||||||
|
|
||||||
|
// install the shadow mask texture as the second texture
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
_shadowMaskTextureName = [self textureForImageNamed:@"ShadowMask"];
|
||||||
|
|
||||||
|
// otherwise, we'll be working on the first texture
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
// get the shader ready, set the clear colour
|
// get the shader ready, set the clear colour
|
||||||
[self.openGLContext makeCurrentContext];
|
[self.openGLContext makeCurrentContext];
|
||||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||||
@@ -87,6 +112,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
|
|||||||
glDeleteBuffers(1, &_arrayBuffer);
|
glDeleteBuffers(1, &_arrayBuffer);
|
||||||
glDeleteVertexArrays(1, &_vertexArray);
|
glDeleteVertexArrays(1, &_vertexArray);
|
||||||
glDeleteTextures(1, &_textureName);
|
glDeleteTextures(1, &_textureName);
|
||||||
|
glDeleteTextures(1, &_shadowMaskTextureName);
|
||||||
glDeleteProgram(_shaderProgram);
|
glDeleteProgram(_shaderProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,6 +127,8 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
|
|||||||
NSPoint viewSize = [self convertPointToBacking:backingSize];
|
NSPoint viewSize = [self convertPointToBacking:backingSize];
|
||||||
glViewport(0, 0, (GLsizei)viewSize.x, (GLsizei)viewSize.y);
|
glViewport(0, 0, (GLsizei)viewSize.x, (GLsizei)viewSize.y);
|
||||||
|
|
||||||
|
glUniform2f(_windowSizeUniform, (GLfloat)viewSize.x, (GLfloat)viewSize.y);
|
||||||
|
|
||||||
CGLUnlockContext([[self openGLContext] CGLContextObj]);
|
CGLUnlockContext([[self openGLContext] CGLContextObj]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,9 +214,12 @@ static NSString *const vertexShader =
|
|||||||
"out vec2 srcCoordinatesVarying[4];\n"
|
"out vec2 srcCoordinatesVarying[4];\n"
|
||||||
"out float lateralVarying;\n"
|
"out float lateralVarying;\n"
|
||||||
"out float phase;\n"
|
"out float phase;\n"
|
||||||
|
"out vec2 shadowMaskCoordinates;\n"
|
||||||
"\n"
|
"\n"
|
||||||
"uniform vec2 textureSize;\n"
|
"uniform vec2 textureSize;\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
"const float shadowMaskMultiple = 300;\n"
|
||||||
|
"\n"
|
||||||
"void main (void)\n"
|
"void main (void)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"srcCoordinatesVarying[0] = vec2(srcCoordinates.x / textureSize.x, (srcCoordinates.y + 0.5) / textureSize.y);\n"
|
"srcCoordinatesVarying[0] = vec2(srcCoordinates.x / textureSize.x, (srcCoordinates.y + 0.5) / textureSize.y);\n"
|
||||||
@@ -200,6 +231,8 @@ static NSString *const vertexShader =
|
|||||||
"lateralVarying = lateral + 1.0707963267949;\n"
|
"lateralVarying = lateral + 1.0707963267949;\n"
|
||||||
"phase = srcCoordinates.x * 6.283185308;\n"
|
"phase = srcCoordinates.x * 6.283185308;\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
"shadowMaskCoordinates = position * vec2(shadowMaskMultiple, shadowMaskMultiple * 0.85057471264368);\n"
|
||||||
|
"\n"
|
||||||
"gl_Position = vec4(position.x * 2.0 - 1.0, 1.0 - position.y * 2.0 + position.x / 131.0, 0.0, 1.0);\n"
|
"gl_Position = vec4(position.x * 2.0 - 1.0, 1.0 - position.y * 2.0 + position.x / 131.0, 0.0, 1.0);\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
@@ -211,13 +244,18 @@ static NSString *const fragmentShader =
|
|||||||
"in vec2 srcCoordinatesVarying[4];\n"
|
"in vec2 srcCoordinatesVarying[4];\n"
|
||||||
"in float lateralVarying;\n"
|
"in float lateralVarying;\n"
|
||||||
"in float phase;\n"
|
"in float phase;\n"
|
||||||
|
"in vec2 shadowMaskCoordinates;\n"
|
||||||
"out vec4 fragColour;\n"
|
"out vec4 fragColour;\n"
|
||||||
"\n"
|
"\n"
|
||||||
"uniform sampler2D texID;\n"
|
"uniform sampler2D texID;\n"
|
||||||
|
"uniform sampler2D shadowMaskTexID;\n"
|
||||||
"uniform float alpha;\n"
|
"uniform float alpha;\n"
|
||||||
"\n"
|
"\n"
|
||||||
"%@"
|
"%@"
|
||||||
"\n"
|
"\n"
|
||||||
|
"// for conversion from i and q are in the range [-0.5, 0.5] (so i needs to be multiplied by 1.1914 and q by 1.0452)\n"
|
||||||
|
"const mat3 yiqToRGB = mat3(1.0, 1.0, 1.0, 1.1389784, -0.3240608, -1.3176884, 0.6490692, -0.6762444, 1.7799756);\n"
|
||||||
|
"\n"
|
||||||
"void main(void)\n"
|
"void main(void)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"vec4 angles = vec4(phase) + vec4(-2.35619449019234, -0.78539816339745, 0.78539816339745, 2.35619449019234);\n"
|
"vec4 angles = vec4(phase) + vec4(-2.35619449019234, -0.78539816339745, 0.78539816339745, 2.35619449019234);\n"
|
||||||
@@ -234,9 +272,7 @@ static NSString *const fragmentShader =
|
|||||||
"float i = dot(cos(angles), samples);\n"
|
"float i = dot(cos(angles), samples);\n"
|
||||||
"float q = dot(sin(angles), samples);\n"
|
"float q = dot(sin(angles), samples);\n"
|
||||||
"\n"
|
"\n"
|
||||||
"// now i and q are in the range [-0.5, 0.5], so i needs to be multiplied by 1.1914 and q by 1.0452\n"
|
"fragColour = 5.0 * texture(shadowMaskTexID, shadowMaskCoordinates) * vec4(yiqToRGB * vec3(y, i, q), 1.0);//sin(lateralVarying));\n"
|
||||||
"const mat3 yiqToRGB = mat3(1.0, 1.0, 1.0, 1.1389784, -0.3240608, -1.3176884, 0.6490692, -0.6762444, 1.7799756);\n"
|
|
||||||
"fragColour = vec4( yiqToRGB * vec3(y, i, q), 1.0);//sin(lateralVarying));\n"
|
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
@@ -306,9 +342,15 @@ static NSString *const fragmentShader =
|
|||||||
_positionAttribute = glGetAttribLocation(_shaderProgram, "position");
|
_positionAttribute = glGetAttribLocation(_shaderProgram, "position");
|
||||||
_textureCoordinatesAttribute = glGetAttribLocation(_shaderProgram, "srcCoordinates");
|
_textureCoordinatesAttribute = glGetAttribLocation(_shaderProgram, "srcCoordinates");
|
||||||
_lateralAttribute = glGetAttribLocation(_shaderProgram, "lateral");
|
_lateralAttribute = glGetAttribLocation(_shaderProgram, "lateral");
|
||||||
_texIDUniform = glGetUniformLocation(_shaderProgram, "texID");
|
|
||||||
_alphaUniform = glGetUniformLocation(_shaderProgram, "alpha");
|
_alphaUniform = glGetUniformLocation(_shaderProgram, "alpha");
|
||||||
_textureSizeUniform = glGetUniformLocation(_shaderProgram, "textureSize");
|
_textureSizeUniform = glGetUniformLocation(_shaderProgram, "textureSize");
|
||||||
|
_windowSizeUniform = glGetUniformLocation(_shaderProgram, "windowSize");
|
||||||
|
|
||||||
|
GLint texIDUniform = glGetUniformLocation(_shaderProgram, "texID");
|
||||||
|
GLint shadowMaskTexIDUniform = glGetUniformLocation(_shaderProgram, "shadowMaskTexID");
|
||||||
|
|
||||||
|
glUniform1i(texIDUniform, 0);
|
||||||
|
glUniform1i(shadowMaskTexIDUniform, 1);
|
||||||
|
|
||||||
glEnableVertexAttribArray((GLuint)_positionAttribute);
|
glEnableVertexAttribArray((GLuint)_positionAttribute);
|
||||||
glEnableVertexAttribArray((GLuint)_textureCoordinatesAttribute);
|
glEnableVertexAttribArray((GLuint)_textureCoordinatesAttribute);
|
||||||
|
Reference in New Issue
Block a user