mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-01 18:50:16 +03:00
Single pass subpixel rendering in OpenGL 2 context.
Fix unit-tests build issue.
This commit is contained in:
@@ -44,6 +44,8 @@ typedef void( APIENTRY* pglBlendFuncSeparate )( GLenum sfactorRGB, GLenum dfacto
|
||||
typedef void( APIENTRY* pglDiscardFramebufferEXT )( GLenum target, GLsizei numAttachments,
|
||||
const GLenum* attachments );
|
||||
typedef void( APIENTRY* pglBlendEquationSeparate )( GLenum modeRGB, GLenum modeAlpha );
|
||||
typedef void( APIENTRY* pglBindFragDataLocationIndexed )( GLuint program, GLuint colorNumber,
|
||||
GLuint index, const GLchar* name );
|
||||
typedef void( APIENTRY* pglBlitFramebufferEXT )( GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||
GLbitfield mask, GLenum filter );
|
||||
|
||||
@@ -260,6 +260,8 @@ void Renderer::init() {
|
||||
writeExtension( EEGL_EXT_blend_func_separate, GLEW_EXT_blend_func_separate );
|
||||
writeExtension( EEGL_EXT_blend_minmax, GLEW_EXT_blend_minmax );
|
||||
writeExtension( EEGL_EXT_blend_subtract, GLEW_EXT_blend_subtract );
|
||||
writeExtension( EEGL_ARB_blend_func_extended,
|
||||
GLEW_ARB_blend_func_extended || GLEW_VERSION_3_3 );
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@@ -296,6 +298,9 @@ void Renderer::init() {
|
||||
glVersion >= 140 || isExtension( "GL_EXT_blend_minmax" ) );
|
||||
writeExtension( EEGL_EXT_blend_subtract,
|
||||
glVersion >= 140 || isExtension( "GL_EXT_blend_subtract" ) );
|
||||
writeExtension( EEGL_ARB_blend_func_extended,
|
||||
!is_es &&
|
||||
( glVersion >= 330 || isExtension( "GL_ARB_blend_func_extended" ) ) );
|
||||
}
|
||||
|
||||
// NVIDIA added support for GL_OES_compressed_ETC1_RGB8_texture in desktop GPUs
|
||||
@@ -477,6 +482,9 @@ void Renderer::drawArrays( unsigned int mode, int first, int count ) {
|
||||
}
|
||||
|
||||
bool Renderer::drawSubpixelArrays( unsigned int mode, int first, int count ) {
|
||||
if ( drawSubpixelDualSourceArrays( mode, first, count ) )
|
||||
return true;
|
||||
|
||||
if ( !setTextureColorMode( 1 ) )
|
||||
return false;
|
||||
|
||||
@@ -497,6 +505,10 @@ bool Renderer::drawSubpixelArrays( unsigned int mode, int first, int count ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Renderer::drawSubpixelDualSourceArrays( unsigned int, int, int ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Renderer::drawSubpixelFallbackArrays( unsigned int mode, int first, int count ) {
|
||||
if ( !setTextureColorMode( 4 ) )
|
||||
return false;
|
||||
@@ -563,6 +575,21 @@ void Renderer::blendEquationSeparate( unsigned int modeRGB, unsigned int modeAlp
|
||||
eeglBlendEquationSeparate( modeRGB, modeAlpha );
|
||||
}
|
||||
|
||||
bool Renderer::bindFragDataLocationIndexed( unsigned int program, unsigned int colorNumber,
|
||||
unsigned int index, const char* name ) {
|
||||
#ifndef EE_GLES
|
||||
static pglBindFragDataLocationIndexed bindFragDataLocationIndexed = NULL;
|
||||
if ( NULL == bindFragDataLocationIndexed )
|
||||
bindFragDataLocationIndexed =
|
||||
(pglBindFragDataLocationIndexed)getProcAddress( "glBindFragDataLocationIndexed" );
|
||||
if ( NULL != bindFragDataLocationIndexed ) {
|
||||
bindFragDataLocationIndexed( program, colorNumber, index, name );
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
void Renderer::blitFrameBuffer( int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0,
|
||||
int dstX1, int dstY1, unsigned int mask, unsigned int filter ) {
|
||||
static pglBlitFramebufferEXT eeglBlitFramebufferEXT = NULL;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <eepp/graphics/blendmode.hpp>
|
||||
#include <eepp/graphics/renderer/openglext.hpp>
|
||||
#include <eepp/graphics/renderer/renderergl.hpp>
|
||||
|
||||
@@ -107,6 +108,73 @@ void main() {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool RendererGL::ensureSubpixelDualSourceShader() {
|
||||
#ifndef EE_GLES1
|
||||
if ( mSubpixelDualSourceShader )
|
||||
return true;
|
||||
if ( mSubpixelDualSourceShaderInitializationAttempted ||
|
||||
!isExtension( EEGL_ARB_blend_func_extended ) || !shadersSupported() )
|
||||
return false;
|
||||
mSubpixelDualSourceShaderInitializationAttempted = true;
|
||||
static const char vertexShader[] = R"(
|
||||
#version 130
|
||||
varying vec4 dgl_Color;
|
||||
varying vec2 dgl_TexCoord;
|
||||
void main() {
|
||||
gl_Position = ftransform();
|
||||
gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
|
||||
dgl_Color = gl_Color;
|
||||
dgl_TexCoord = ( gl_TextureMatrix[0] * gl_MultiTexCoord0 ).xy;
|
||||
}
|
||||
)";
|
||||
static const char fragmentShader[] = R"(
|
||||
#version 130
|
||||
uniform sampler2D textureUnit0;
|
||||
varying vec4 dgl_Color;
|
||||
varying vec2 dgl_TexCoord;
|
||||
out vec4 dgl_FragColor;
|
||||
out vec4 dgl_FragCoverage;
|
||||
void main() {
|
||||
vec3 coverage = texture2D( textureUnit0, dgl_TexCoord ).rgb;
|
||||
float meanCoverage = dot( coverage, vec3( 1.0 / 3.0 ) );
|
||||
dgl_FragColor = vec4( dgl_Color.rgb, dgl_Color.a * meanCoverage );
|
||||
dgl_FragCoverage = vec4( dgl_Color.a * coverage, 0.0 );
|
||||
}
|
||||
)";
|
||||
ShaderProgramPtr shader = ShaderProgram::New( "eepp-subpixel-dual-source-text" );
|
||||
ShaderPtr vs( eeNew( VertexShader, ( vertexShader, sizeof( vertexShader ) - 1 ) ),
|
||||
ResourceDeleter<Shader>() );
|
||||
ShaderPtr fs( eeNew( FragmentShader, ( fragmentShader, sizeof( fragmentShader ) - 1 ) ),
|
||||
ResourceDeleter<Shader>() );
|
||||
if ( shader && vs->isValid() && fs->isValid() ) {
|
||||
shader->addShader( std::move( vs ) );
|
||||
shader->addShader( std::move( fs ) );
|
||||
if ( shader->bindFragDataLocationIndexed( 0, 0, "dgl_FragColor" ) &&
|
||||
shader->bindFragDataLocationIndexed( 0, 1, "dgl_FragCoverage" ) && shader->link() ) {
|
||||
mSubpixelDualSourceShader = std::move( shader );
|
||||
Renderer::setShader( mSubpixelDualSourceShader.get() );
|
||||
mSubpixelDualSourceShader->setUniform( "textureUnit0", 0 );
|
||||
Renderer::setShader( mPreviousShader );
|
||||
}
|
||||
}
|
||||
return !!mSubpixelDualSourceShader;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool RendererGL::drawSubpixelDualSourceArrays( unsigned int mode, int first, int count ) {
|
||||
if ( !ensureSubpixelDualSourceShader() )
|
||||
return false;
|
||||
const BlendMode previousBlendMode = BlendMode::getPreBlendFunc();
|
||||
Renderer::setShader( mSubpixelDualSourceShader.get() );
|
||||
blendFuncSeparate( GL_SRC1_COLOR, GL_ONE_MINUS_SRC1_COLOR, GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
|
||||
drawArrays( mode, first, count );
|
||||
BlendMode::setMode( previousBlendMode, true );
|
||||
Renderer::setShader( mPreviousShader );
|
||||
return true;
|
||||
}
|
||||
|
||||
void RendererGL::setShader( ShaderProgram* shader ) {
|
||||
if ( !mUsingSubpixelShader )
|
||||
mPreviousShader = shader;
|
||||
|
||||
@@ -231,8 +231,19 @@ void ShaderProgram::addShaders( const std::vector<ShaderPtr>& shaders ) {
|
||||
addShader( shader );
|
||||
}
|
||||
|
||||
bool ShaderProgram::bindFragDataLocationIndexed( Uint32 colorNumber, Uint32 index,
|
||||
const char* name ) {
|
||||
if ( !GLi->bindFragDataLocationIndexed( getHandler(), colorNumber, index, name ) )
|
||||
return false;
|
||||
mFragmentOutputBindings.push_back( { colorNumber, index, name } );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShaderProgram::link() {
|
||||
#ifdef EE_SHADERS_SUPPORTED
|
||||
for ( const auto& binding : mFragmentOutputBindings )
|
||||
GLi->bindFragDataLocationIndexed( getHandler(), binding.colorNumber, binding.index,
|
||||
binding.name.c_str() );
|
||||
GLi->linkProgram( getHandler() );
|
||||
|
||||
Int32 linked;
|
||||
|
||||
@@ -130,8 +130,10 @@ UTEST( FontRendering, subpixelCoverageCompositesPerChannel ) {
|
||||
for ( Uint32 y = top; y < bottom; ++y ) {
|
||||
for ( Uint32 x = 0; x < image.getWidth(); ++x ) {
|
||||
Color pixel = image.getPixel( x, y );
|
||||
if ( eeabs( static_cast<Int32>( pixel.r ) - static_cast<Int32>( pixel.g ) ) > 3 ||
|
||||
eeabs( static_cast<Int32>( pixel.g ) - static_cast<Int32>( pixel.b ) ) > 3 )
|
||||
const Int32 redGreenDelta = static_cast<Int32>( pixel.r ) - pixel.g;
|
||||
const Int32 greenBlueDelta = static_cast<Int32>( pixel.g ) - pixel.b;
|
||||
if ( ( redGreenDelta < 0 ? -redGreenDelta : redGreenDelta ) > 3 ||
|
||||
( greenBlueDelta < 0 ? -greenBlueDelta : greenBlueDelta ) > 3 )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user