1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-10-01 13:58:20 +00:00

Made an attempt to reestablish the Atari 2600 output connection despite various changes (TODO: generalise that stuff), and to start creating the composite shader.

This commit is contained in:
Thomas Harte 2016-03-07 21:04:04 -05:00
parent 2de229152f
commit 1e5fe2b2c1
8 changed files with 73 additions and 41 deletions

View File

@ -26,12 +26,12 @@ Machine::Machine() :
{
_crt = new Outputs::CRT(228, 1, Outputs::CRT::DisplayType::NTSC60, 1, 2);
_crt->set_composite_sampling_function(
"float sample(vec2 coordinate, float phase)\n"
"float composite_sample(vec2 coordinate, float phase)\n"
"{\n"
"vec2 c = texture(texID, coordinate).rg;"
"float y = 0.1 + c.x * 0.91071428571429;\n"
"float aOffset = 6.283185308 * (c.y - 3.0 / 16.0) * 1.14285714285714;\n"
"return y + step(0.03125, c.y) * 0.1 * cos(phase - aOffset);\n"
"return y + step(0.03125, c.y) * 0.1 * cos((coordinate.x * 2.0 * 3.141592654) - aOffset);\n"
"}");
_crt->set_output_device(Outputs::CRT::Television);
memset(_collisions, 0xff, sizeof(_collisions));

View File

@ -40,7 +40,7 @@ Machine::Machine() :
"float texValue = texture(texID, coordinate).r;"
"return vec4(step(4.0/256.0, mod(texValue, 8.0/256.0)), step(2.0/256.0, mod(texValue, 4.0/256.0)), step(1.0/256.0, mod(texValue, 2.0/256.0)), 1.0);"
"}");
_crt->set_output_device(Outputs::CRT::Monitor);
_crt->set_output_device(Outputs::CRT::Television);
// _crt->set_visible_area(Outputs::Rect(0.23108f, 0.0f, 0.8125f, 0.98f)); //1875
memset(_key_states, 0, sizeof(_key_states));

View File

@ -54,6 +54,10 @@ class Atari2600Document: MachineDocument {
atari2600.runForNumberOfCycles(numberOfCycles)
}
override func openGLView(view: CSOpenGLView, drawViewOnlyIfDirty onlyIfDirty: Bool) {
atari2600.drawViewForPixelSize(view.backingSize, onlyIfDirty: onlyIfDirty)
}
// MARK: CSOpenGLViewResponderDelegate
private func inputForKey(event: NSEvent) -> Atari2600DigitalInput? {

View File

@ -15,4 +15,6 @@
- (void)setState:(BOOL)state forDigitalInput:(Atari2600DigitalInput)digitalInput;
- (void)setResetLineEnabled:(BOOL)enabled;
- (void)drawViewForPixelSize:(CGSize)pixelSize onlyIfDirty:(BOOL)onlyIfDirty;
@end

View File

@ -47,6 +47,10 @@
_atari2600.run_for_cycles(numberOfCycles);
}
- (void)drawViewForPixelSize:(CGSize)pixelSize onlyIfDirty:(BOOL)onlyIfDirty {
_atari2600.get_crt()->draw_frame((unsigned int)pixelSize.width, (unsigned int)pixelSize.height, onlyIfDirty ? true : false);
}
- (void)setROM:(NSData *)rom {
[self perform:^{
_atari2600.set_rom(rom.length, (const uint8_t *)rom.bytes);

View File

@ -54,10 +54,6 @@
return YES;
}
- (void)setView:(CSOpenGLView *)view {
[super setView:view];
}
- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed {
switch(key)
{

View File

@ -373,6 +373,7 @@ class CRT {
// Methods used by the OpenGL code
void prepare_rgb_output_shader();
void prepare_composite_input_shader();
void prepare_vertex_array();
void push_size_uniforms(unsigned int output_width, unsigned int output_height);

View File

@ -17,7 +17,7 @@
using namespace Outputs;
struct CRT::OpenGLState {
std::unique_ptr<OpenGL::Shader> shaderProgram;
std::unique_ptr<OpenGL::Shader> rgb_shader_program, composite_input_shader_program;
GLuint arrayBuffer, vertexArray;
size_t verticesPerSlice;
@ -38,6 +38,10 @@ struct CRT::OpenGLState {
std::unique_ptr<OpenGL::TextureTarget> filteredTexture; // receives filtered YIQ or YUV
};
namespace {
static const GLenum first_supplied_buffer_texture_unit = 3;
}
static GLenum formatForDepth(size_t depth)
{
switch(depth)
@ -75,7 +79,7 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool
for(unsigned int buffer = 0; buffer < _buffer_builder->number_of_buffers; buffer++)
{
glGenTextures(1, &_openGL_state->textureName);
glActiveTexture(GL_TEXTURE3 + buffer);
glActiveTexture(GL_TEXTURE0 + first_supplied_buffer_texture_unit + buffer);
glBindTexture(GL_TEXTURE_2D, _openGL_state->textureName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@ -90,6 +94,7 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool
glGenBuffers(1, &_openGL_state->arrayBuffer);
_openGL_state->verticesPerSlice = 0;
prepare_composite_input_shader();
prepare_rgb_output_shader();
glBindBuffer(GL_ARRAY_BUFFER, _openGL_state->arrayBuffer);
@ -131,7 +136,7 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool
// time as it may have had extra data appended to it
for(unsigned int buffer = 0; buffer < _buffer_builder->number_of_buffers; buffer++)
{
glActiveTexture(GL_TEXTURE3 + buffer);
glActiveTexture(GL_TEXTURE0 + first_supplied_buffer_texture_unit + buffer);
GLenum format = formatForDepth(_buffer_builder->buffers[0].bytes_per_pixel);
if(_buffer_builder->_next_write_y_position < _buffer_builder->last_uploaded_line)
{
@ -260,13 +265,13 @@ char *CRT::get_input_vertex_shader()
"uniform vec2 textureSize;"
"uniform float phaseCyclesPerTick;"
"out vec2 inputPositionVerying;"
"out vec2 inputPositionVarying;"
"out float phaseVarying;"
"void main(void)"
"{"
"inputPositionVerying = inputPosition;"
"gl_Position = vec4(outputPosition.x * 2.0 / textureSize.width - 1.0, outputPosition.y * 2.0 / textureSize.height - 1.0, 0.0, 1.0);"
"inputPositionVarying = inputPosition;"
"gl_Position = vec4(outputPosition.x * 2.0 / textureSize.x - 1.0, outputPosition.y * 2.0 / textureSize.y - 1.0, 0.0, 1.0);"
"phaseVarying = (phaseCyclesPerTick * phaseTime + phaseAndAmplitude.x) * 2.0 * 3.141592654;"
"}");
}
@ -281,7 +286,7 @@ char *CRT::get_input_fragment_shader()
return get_compound_shader(
"#version 150\n"
"in vec2 inputPositionVerying;"
"in vec2 inputPositionVarying;"
"in float phaseVarying;"
"out vec4 fragColour;"
@ -439,6 +444,7 @@ char *CRT::get_output_fragment_shader(const char *sampling_function)
char *CRT::get_compound_shader(const char *base, const char *insert)
{
if(!base || !insert) return nullptr;
size_t totalLength = strlen(base) + strlen(insert) + 1;
char *text = new char[totalLength];
snprintf(text, totalLength, base, insert);
@ -447,43 +453,62 @@ char *CRT::get_compound_shader(const char *base, const char *insert)
#pragma mark - Program compilation
void CRT::prepare_composite_input_shader()
{
char *vertex_shader = get_input_vertex_shader();
char *fragment_shader = get_input_fragment_shader();
if(vertex_shader && fragment_shader)
{
_openGL_state->composite_input_shader_program = std::unique_ptr<OpenGL::Shader>(new OpenGL::Shader(vertex_shader, fragment_shader));
}
free(vertex_shader);
free(fragment_shader);
}
void CRT::prepare_rgb_output_shader()
{
char *vertex_shader = get_output_vertex_shader();
char *fragment_shader = get_rgb_output_fragment_shader();
_openGL_state->shaderProgram = std::unique_ptr<OpenGL::Shader>(new OpenGL::Shader(vertex_shader, fragment_shader));
_openGL_state->shaderProgram->bind();
if(vertex_shader && fragment_shader)
{
_openGL_state->rgb_shader_program = std::unique_ptr<OpenGL::Shader>(new OpenGL::Shader(vertex_shader, fragment_shader));
_openGL_state->positionAttribute = _openGL_state->shaderProgram->get_attrib_location("position");
_openGL_state->textureCoordinatesAttribute = _openGL_state->shaderProgram->get_attrib_location("srcCoordinates");
_openGL_state->lateralAttribute = _openGL_state->shaderProgram->get_attrib_location("lateral");
_openGL_state->timestampAttribute = _openGL_state->shaderProgram->get_attrib_location("timestamp");
_openGL_state->rgb_shader_program->bind();
_openGL_state->windowSizeUniform = _openGL_state->shaderProgram->get_uniform_location("windowSize");
_openGL_state->boundsSizeUniform = _openGL_state->shaderProgram->get_uniform_location("boundsSize");
_openGL_state->boundsOriginUniform = _openGL_state->shaderProgram->get_uniform_location("boundsOrigin");
_openGL_state->timestampBaseUniform = _openGL_state->shaderProgram->get_uniform_location("timestampBase");
_openGL_state->positionAttribute = _openGL_state->rgb_shader_program->get_attrib_location("position");
_openGL_state->textureCoordinatesAttribute = _openGL_state->rgb_shader_program->get_attrib_location("srcCoordinates");
_openGL_state->lateralAttribute = _openGL_state->rgb_shader_program->get_attrib_location("lateral");
_openGL_state->timestampAttribute = _openGL_state->rgb_shader_program->get_attrib_location("timestamp");
GLint texIDUniform = _openGL_state->shaderProgram->get_uniform_location("texID");
GLint shadowMaskTexIDUniform = _openGL_state->shaderProgram->get_uniform_location("shadowMaskTexID");
GLint textureSizeUniform = _openGL_state->shaderProgram->get_uniform_location("textureSize");
GLint ticksPerFrameUniform = _openGL_state->shaderProgram->get_uniform_location("ticksPerFrame");
GLint scanNormalUniform = _openGL_state->shaderProgram->get_uniform_location("scanNormal");
GLint positionConversionUniform = _openGL_state->shaderProgram->get_uniform_location("positionConversion");
_openGL_state->windowSizeUniform = _openGL_state->rgb_shader_program->get_uniform_location("windowSize");
_openGL_state->boundsSizeUniform = _openGL_state->rgb_shader_program->get_uniform_location("boundsSize");
_openGL_state->boundsOriginUniform = _openGL_state->rgb_shader_program->get_uniform_location("boundsOrigin");
_openGL_state->timestampBaseUniform = _openGL_state->rgb_shader_program->get_uniform_location("timestampBase");
glUniform1i(texIDUniform, 3);
glUniform1i(shadowMaskTexIDUniform, 1);
glUniform2f(textureSizeUniform, CRTInputBufferBuilderWidth, CRTInputBufferBuilderHeight);
glUniform1f(ticksPerFrameUniform, (GLfloat)(_cycles_per_line * _height_of_display));
glUniform2f(positionConversionUniform, _horizontal_flywheel->get_scan_period(), _vertical_flywheel->get_scan_period() / (unsigned int)_vertical_flywheel_output_divider);
GLint texIDUniform = _openGL_state->rgb_shader_program->get_uniform_location("texID");
GLint shadowMaskTexIDUniform = _openGL_state->rgb_shader_program->get_uniform_location("shadowMaskTexID");
GLint textureSizeUniform = _openGL_state->rgb_shader_program->get_uniform_location("textureSize");
GLint ticksPerFrameUniform = _openGL_state->rgb_shader_program->get_uniform_location("ticksPerFrame");
GLint scanNormalUniform = _openGL_state->rgb_shader_program->get_uniform_location("scanNormal");
GLint positionConversionUniform = _openGL_state->rgb_shader_program->get_uniform_location("positionConversion");
float scan_angle = atan2f(1.0f / (float)_height_of_display, 1.0f);
float scan_normal[] = { -sinf(scan_angle), cosf(scan_angle)};
float multiplier = (float)_horizontal_flywheel->get_standard_period() / ((float)_height_of_display * (float)_horizontal_flywheel->get_scan_period());
scan_normal[0] *= multiplier;
scan_normal[1] *= multiplier;
glUniform2f(scanNormalUniform, scan_normal[0], scan_normal[1]);
glUniform1i(texIDUniform, first_supplied_buffer_texture_unit);
glUniform1i(shadowMaskTexIDUniform, 1);
glUniform2f(textureSizeUniform, CRTInputBufferBuilderWidth, CRTInputBufferBuilderHeight);
glUniform1f(ticksPerFrameUniform, (GLfloat)(_cycles_per_line * _height_of_display));
glUniform2f(positionConversionUniform, _horizontal_flywheel->get_scan_period(), _vertical_flywheel->get_scan_period() / (unsigned int)_vertical_flywheel_output_divider);
float scan_angle = atan2f(1.0f / (float)_height_of_display, 1.0f);
float scan_normal[] = { -sinf(scan_angle), cosf(scan_angle)};
float multiplier = (float)_horizontal_flywheel->get_standard_period() / ((float)_height_of_display * (float)_horizontal_flywheel->get_scan_period());
scan_normal[0] *= multiplier;
scan_normal[1] *= multiplier;
glUniform2f(scanNormalUniform, scan_normal[0], scan_normal[1]);
}
free(vertex_shader);
free(fragment_shader);
}
void CRT::prepare_vertex_array()