mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-25 03:32:01 +00:00
Eliminates the concept of an iCoordinate.
Real-life precision appears not to support the idea of sub-sample pixel storage.
This commit is contained in:
parent
c6e94bc2a6
commit
a38639d099
@ -69,7 +69,7 @@ template <class BusHandler> class MOS6560 {
|
||||
speaker_(audio_generator_)
|
||||
{
|
||||
crt_->set_svideo_sampling_function(
|
||||
"vec2 svideo_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)"
|
||||
"vec2 svideo_sample(usampler2D texID, vec2 coordinate, float phase, float amplitude)"
|
||||
"{"
|
||||
"vec2 yc = texture(texID, coordinate).rg / vec2(255.0);"
|
||||
|
||||
|
@ -92,7 +92,7 @@ TMS9918::TMS9918(Personality p) {
|
||||
// Unimaginatively, this class just passes RGB through to the shader. Investigation is needed
|
||||
// into whether there's a more natural form.
|
||||
crt_->set_rgb_sampling_function(
|
||||
"vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)"
|
||||
"vec3 rgb_sample(usampler2D sampler, vec2 coordinate)"
|
||||
"{"
|
||||
"return texture(sampler, coordinate).rgb / vec3(255.0);"
|
||||
"}");
|
||||
|
@ -327,7 +327,7 @@ class CRTCBusHandler {
|
||||
void setup_output(float aspect_ratio) {
|
||||
crt_.reset(new Outputs::CRT::CRT(1024, 16, Outputs::CRT::DisplayType::PAL50, 1));
|
||||
crt_->set_rgb_sampling_function(
|
||||
"vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)"
|
||||
"vec3 rgb_sample(usampler2D sampler, vec2 coordinate)"
|
||||
"{"
|
||||
"uint sample = texture(texID, coordinate).r;"
|
||||
"return vec3(float((sample >> 4) & 3u), float((sample >> 2) & 3u), float(sample & 3u)) / 2.0;"
|
||||
|
@ -18,7 +18,7 @@ VideoBase::VideoBase(bool is_iie, std::function<void(Cycles)> &&target) :
|
||||
// Set a composite sampling function that assumes one byte per pixel input, and
|
||||
// accepts any non-zero value as being fully on, zero being fully off.
|
||||
crt_->set_composite_sampling_function(
|
||||
"float composite_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate, float phase, float amplitude)"
|
||||
"float composite_sample(usampler2D sampler, vec2 coordinate, float phase, float amplitude)"
|
||||
"{"
|
||||
"return clamp(texture(sampler, coordinate).r, 0.0, 1.0);"
|
||||
"}");
|
||||
|
@ -124,7 +124,7 @@ void TIA::set_output_mode(Atari2600::TIA::OutputMode output_mode) {
|
||||
|
||||
if(output_mode == OutputMode::NTSC) {
|
||||
crt_->set_svideo_sampling_function(
|
||||
"vec2 svideo_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)"
|
||||
"vec2 svideo_sample(usampler2D texID, vec2 coordinate, float phase, float amplitude)"
|
||||
"{"
|
||||
"uint c = texture(texID, coordinate).r;"
|
||||
"uint y = c & 14u;"
|
||||
@ -136,7 +136,7 @@ void TIA::set_output_mode(Atari2600::TIA::OutputMode output_mode) {
|
||||
display_type = Outputs::CRT::DisplayType::NTSC60;
|
||||
} else {
|
||||
crt_->set_svideo_sampling_function(
|
||||
"vec2 svideo_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)"
|
||||
"vec2 svideo_sample(usampler2D texID, vec2 coordinate, float phase, float amplitude)"
|
||||
"{"
|
||||
"uint c = texture(texID, coordinate).r;"
|
||||
"uint y = c & 14u;"
|
||||
|
@ -52,13 +52,11 @@ VideoOutput::VideoOutput(uint8_t *memory) : ram_(memory) {
|
||||
|
||||
crt_.reset(new Outputs::CRT::CRT(crt_cycles_per_line, 8, Outputs::CRT::DisplayType::PAL50, 1));
|
||||
crt_->set_rgb_sampling_function(
|
||||
"vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)"
|
||||
"vec3 rgb_sample(usampler2D sampler, vec2 coordinate)"
|
||||
"{"
|
||||
"uint texValue = texture(sampler, coordinate).r;"
|
||||
"texValue >>= 4 - (int(icoordinate.x) & 4);"
|
||||
"return vec3( uvec3(texValue) & uvec3(4u, 2u, 1u));"
|
||||
"}");
|
||||
crt_->set_integer_coordinate_multiplier(8.0f);
|
||||
std::unique_ptr<Outputs::CRT::TextureBuilder::Bookender> bookender(new FourBPPBookender);
|
||||
crt_->set_bookender(std::move(bookender));
|
||||
// TODO: as implied below, I've introduced a clock's latency into the graphics pipeline somehow. Investigate.
|
||||
|
@ -25,13 +25,13 @@ VideoOutput::VideoOutput(uint8_t *memory) :
|
||||
v_sync_start_position_(PAL50VSyncStartPosition), v_sync_end_position_(PAL50VSyncEndPosition),
|
||||
counter_period_(PAL50Period) {
|
||||
crt_->set_rgb_sampling_function(
|
||||
"vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)"
|
||||
"vec3 rgb_sample(usampler2D sampler, vec2 coordinate)"
|
||||
"{"
|
||||
"uint texValue = texture(sampler, coordinate).r;"
|
||||
"return vec3( uvec3(texValue) & uvec3(4u, 2u, 1u));"
|
||||
"}");
|
||||
crt_->set_composite_sampling_function(
|
||||
"float composite_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate, float phase, float amplitude)"
|
||||
"float composite_sample(usampler2D sampler, vec2 coordinate, float phase, float amplitude)"
|
||||
"{"
|
||||
"uint texValue = uint(dot(texture(sampler, coordinate).rg, uvec2(1, 256)));"
|
||||
"uint iPhase = uint((phase + 3.141592654 + 0.39269908175) * 2.0 / 3.141592654) & 3u;"
|
||||
|
@ -26,7 +26,7 @@ Video::Video() :
|
||||
// Set a composite sampling function that assumes two-level input; either a byte is 0, which is black,
|
||||
// or it is non-zero, which is white.
|
||||
crt_->set_composite_sampling_function(
|
||||
"float composite_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate, float phase, float amplitude)"
|
||||
"float composite_sample(usampler2D sampler, vec2 coordinate, float phase, float amplitude)"
|
||||
"{"
|
||||
"return texture(sampler, coordinate).r;"
|
||||
"}");
|
||||
|
@ -280,7 +280,7 @@ class CRT {
|
||||
/*! Sets a function that will map from whatever data the machine provided to a composite signal.
|
||||
|
||||
@param shader A GLSL fragment including a function with the signature
|
||||
`float composite_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)`
|
||||
`float composite_sample(usampler2D texID, vec2 coordinate, float phase, float amplitude)`
|
||||
that evaluates to the composite signal level as a function of a source buffer, sampling location, colour
|
||||
carrier phase and amplitude.
|
||||
*/
|
||||
@ -290,22 +290,6 @@ class CRT {
|
||||
});
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets a multiplier applied to iCoordinate values prior to their passing to the various sampling functions.
|
||||
This multiplier is applied outside of the interpolation loop, making for a more precise interpolation
|
||||
than if it were applied within the sampling function.
|
||||
|
||||
Idiomatically, this is likely to be the number of output pixels packed into each input sample where
|
||||
packing is in use.
|
||||
|
||||
The default value is 1.0.
|
||||
*/
|
||||
inline void set_integer_coordinate_multiplier(float multiplier) {
|
||||
enqueue_openGL_function([=] {
|
||||
openGL_output_builder_.set_integer_coordinate_multiplier(multiplier);
|
||||
});
|
||||
}
|
||||
|
||||
enum CompositeSourceType {
|
||||
/// The composite function provides continuous output.
|
||||
Continuous,
|
||||
|
@ -524,12 +524,4 @@ void OpenGLOutputBuilder::set_timing_uniforms() {
|
||||
if(rgb_input_shader_program_) {
|
||||
rgb_input_shader_program_->set_width_scalers(1.0f, 1.0f);
|
||||
}
|
||||
set_integer_coordinate_multiplier(integer_coordinate_multiplier_);
|
||||
}
|
||||
|
||||
void OpenGLOutputBuilder::set_integer_coordinate_multiplier(float multiplier) {
|
||||
integer_coordinate_multiplier_ = multiplier;
|
||||
if(composite_input_shader_program_) composite_input_shader_program_->set_integer_coordinate_multiplier(multiplier);
|
||||
if(svideo_input_shader_program_) svideo_input_shader_program_->set_integer_coordinate_multiplier(multiplier);
|
||||
if(rgb_input_shader_program_) rgb_input_shader_program_->set_integer_coordinate_multiplier(multiplier);
|
||||
}
|
||||
|
@ -105,8 +105,6 @@ class OpenGLOutputBuilder {
|
||||
float get_composite_output_width() const;
|
||||
void set_output_shader_width();
|
||||
|
||||
float integer_coordinate_multiplier_ = 1.0f;
|
||||
|
||||
// Maintain a couple of rectangles for masking off the extreme edge of the display;
|
||||
// this is a bit of a cheat: there's some tolerance in when a sync pulse will be
|
||||
// generated. So it might be slightly later than expected. Which might cause a scan
|
||||
@ -174,7 +172,6 @@ class OpenGLOutputBuilder {
|
||||
void set_rgb_sampling_function(const std::string &);
|
||||
void set_video_signal(VideoSignal);
|
||||
void set_timing(unsigned int input_frequency, unsigned int cycles_per_line, unsigned int height_of_display, unsigned int horizontal_scan_period, unsigned int vertical_scan_period, unsigned int vertical_period_divider);
|
||||
void set_integer_coordinate_multiplier(float multiplier);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -46,11 +46,9 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_shader(const std::s
|
||||
"uniform float inputVerticalOffset;"
|
||||
"uniform float outputVerticalOffset;"
|
||||
"uniform float textureHeightDivisor;"
|
||||
"uniform float iCoordinateMultiplier;"
|
||||
|
||||
"out vec3 phaseAndAmplitudeVarying;"
|
||||
"out vec2 inputPositionsVarying[11];"
|
||||
"out vec2 iInputPositionVarying;"
|
||||
"out vec2 delayLinePositionVarying;"
|
||||
|
||||
"void main(void)"
|
||||
@ -75,9 +73,8 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_shader(const std::s
|
||||
"vec2 extendedInputPosition = " << (input_is_inputPosition ? "inputPosition" : "outputPosition") << " + extensionVector;"
|
||||
"vec2 extendedOutputPosition = outputPosition + extensionVector;"
|
||||
|
||||
// keep iInputPositionVarying in whole source pixels, scale mappedInputPosition to the ordinary normalised range
|
||||
// scale mappedInputPosition to the ordinary normalised range
|
||||
"vec2 textureSize = vec2(textureSize(texID, 0));"
|
||||
"iInputPositionVarying = extendedInputPosition * iCoordinateMultiplier;"
|
||||
"vec2 mappedInputPosition = extendedInputPosition / textureSize;"
|
||||
|
||||
// setup input positions spaced as per the supplied offsets; these are for filtering where required
|
||||
@ -120,7 +117,6 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_composite_source_sh
|
||||
"#version 150\n"
|
||||
|
||||
"in vec2 inputPositionsVarying[11];"
|
||||
"in vec2 iInputPositionVarying;"
|
||||
"in vec3 phaseAndAmplitudeVarying;"
|
||||
|
||||
"out vec4 fragColour;"
|
||||
@ -132,18 +128,18 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_composite_source_sh
|
||||
if(!svideo_shader.empty()) {
|
||||
fragment_shader <<
|
||||
svideo_shader <<
|
||||
"float composite_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)"
|
||||
"float composite_sample(usampler2D texID, vec2 coordinate, float phase, float amplitude)"
|
||||
"{"
|
||||
"vec2 svideoColour = svideo_sample(texID, coordinate, iCoordinate, phase, amplitude);"
|
||||
"vec2 svideoColour = svideo_sample(texID, coordinate, phase, amplitude);"
|
||||
"return mix(svideoColour.x, svideoColour.y, abs(amplitude));"
|
||||
"}";
|
||||
} else {
|
||||
fragment_shader <<
|
||||
rgb_shader <<
|
||||
"uniform mat3 rgbToLumaChroma;"
|
||||
"float composite_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)"
|
||||
"float composite_sample(usampler2D texID, vec2 coordinate, float phase, float amplitude)"
|
||||
"{"
|
||||
"vec3 rgbColour = clamp(rgb_sample(texID, coordinate, iCoordinate), vec3(0.0), vec3(1.0));"
|
||||
"vec3 rgbColour = clamp(rgb_sample(texID, coordinate), vec3(0.0), vec3(1.0));"
|
||||
"vec3 lumaChromaColour = rgbToLumaChroma * rgbColour;"
|
||||
"vec2 quadrature = vec2(cos(phase), sin(phase)) * vec2(abs(amplitude), amplitude);"
|
||||
"return dot(lumaChromaColour, vec3(1.0 - abs(amplitude), quadrature));"
|
||||
@ -154,7 +150,7 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_composite_source_sh
|
||||
fragment_shader <<
|
||||
"void main(void)"
|
||||
"{"
|
||||
"fragColour = vec4(composite_sample(texID, inputPositionsVarying[5], iInputPositionVarying, phaseAndAmplitudeVarying.x, phaseAndAmplitudeVarying.y));"
|
||||
"fragColour = vec4(composite_sample(texID, inputPositionsVarying[5], phaseAndAmplitudeVarying.x, phaseAndAmplitudeVarying.y));"
|
||||
"}";
|
||||
|
||||
return make_shader(fragment_shader.str(), true, true);
|
||||
@ -166,7 +162,6 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_svideo_source_shade
|
||||
"#version 150\n"
|
||||
|
||||
"in vec2 inputPositionsVarying[11];"
|
||||
"in vec2 iInputPositionVarying;"
|
||||
"in vec3 phaseAndAmplitudeVarying;"
|
||||
|
||||
"out vec3 fragColour;"
|
||||
@ -178,9 +173,9 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_svideo_source_shade
|
||||
fragment_shader
|
||||
<< rgb_shader <<
|
||||
"uniform mat3 rgbToLumaChroma;"
|
||||
"vec2 svideo_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)"
|
||||
"vec2 svideo_sample(usampler2D texID, vec2 coordinate, float phase, float amplitude)"
|
||||
"{"
|
||||
"vec3 rgbColour = clamp(rgb_sample(texID, coordinate, iCoordinate), vec3(0.0), vec3(1.0));"
|
||||
"vec3 rgbColour = clamp(rgb_sample(texID, coordinate), vec3(0.0), vec3(1.0));"
|
||||
"vec3 lumaChromaColour = rgbToLumaChroma * rgbColour;"
|
||||
"vec2 quadrature = vec2(cos(phase), sin(phase)) * vec2(1.0, sign(amplitude));"
|
||||
"return vec2(lumaChromaColour.x, 0.5 + dot(quadrature, lumaChromaColour.yz) * 0.5);"
|
||||
@ -190,7 +185,7 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_svideo_source_shade
|
||||
fragment_shader <<
|
||||
"void main(void)"
|
||||
"{"
|
||||
"vec2 sample = svideo_sample(texID, inputPositionsVarying[5], iInputPositionVarying, phaseAndAmplitudeVarying.x, phaseAndAmplitudeVarying.y);"
|
||||
"vec2 sample = svideo_sample(texID, inputPositionsVarying[5], phaseAndAmplitudeVarying.x, phaseAndAmplitudeVarying.y);"
|
||||
"vec2 quadrature = vec2(cos(phaseAndAmplitudeVarying.x), sin(phaseAndAmplitudeVarying.x)) * vec2(1.0, sign(phaseAndAmplitudeVarying.y)) * 0.5 * phaseAndAmplitudeVarying.z;"
|
||||
"fragColour = vec3(sample.x, vec2(0.5) + (sample.y * quadrature));"
|
||||
"}";
|
||||
@ -204,7 +199,6 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_rgb_source_shader(c
|
||||
"#version 150\n"
|
||||
|
||||
"in vec2 inputPositionsVarying[11];"
|
||||
"in vec2 iInputPositionVarying;"
|
||||
"in vec3 phaseAndAmplitudeVarying;"
|
||||
|
||||
"out vec3 fragColour;"
|
||||
@ -215,7 +209,7 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_rgb_source_shader(c
|
||||
|
||||
"void main(void)"
|
||||
"{"
|
||||
"fragColour = rgb_sample(texID, inputPositionsVarying[5], iInputPositionVarying);"
|
||||
"fragColour = rgb_sample(texID, inputPositionsVarying[5]);"
|
||||
"}";
|
||||
|
||||
return make_shader(fragment_shader.str(), true, true);
|
||||
@ -439,7 +433,3 @@ void IntermediateShader::set_is_double_height(bool is_double_height, float input
|
||||
set_uniform("inputVerticalOffset", input_offset);
|
||||
set_uniform("outputVerticalOffset", output_offset);
|
||||
}
|
||||
|
||||
void IntermediateShader::set_integer_coordinate_multiplier(float multiplier) {
|
||||
set_uniform("iCoordinateMultiplier", multiplier);
|
||||
}
|
||||
|
@ -135,11 +135,6 @@ public:
|
||||
*/
|
||||
void set_is_double_height(bool is_double_height, float input_offset = 0.0f, float output_offset = 0.0f);
|
||||
|
||||
/*!
|
||||
Sets the multiplier applied in the vertex shader to iCoordinates.
|
||||
*/
|
||||
void set_integer_coordinate_multiplier(float);
|
||||
|
||||
private:
|
||||
static std::unique_ptr<IntermediateShader> make_shader(const std::string &fragment_shader, bool use_usampler, bool input_is_inputPosition);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user