Added support for geometry shaders
This commit is contained in:
parent
1217699fe0
commit
1763861b26
6 changed files with 359 additions and 33 deletions
|
@ -228,6 +228,10 @@
|
|||
#define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_EXT
|
||||
#define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_EXT
|
||||
|
||||
// Core since 3.2 - ARB_geometry_shader4
|
||||
#define GLEXT_geometry_shader4 sfogl_ext_ARB_geometry_shader4
|
||||
#define GLEXT_GL_GEOMETRY_SHADER GL_GEOMETRY_SHADER_ARB
|
||||
|
||||
#endif
|
||||
|
||||
namespace sf
|
||||
|
|
|
@ -14,3 +14,4 @@ ARB_fragment_shader
|
|||
ARB_texture_non_power_of_two
|
||||
EXT_blend_equation_separate
|
||||
EXT_framebuffer_object
|
||||
ARB_geometry_shader4
|
||||
|
|
|
@ -46,6 +46,7 @@ int sfogl_ext_ARB_fragment_shader = sfogl_LOAD_FAILED;
|
|||
int sfogl_ext_ARB_texture_non_power_of_two = sfogl_LOAD_FAILED;
|
||||
int sfogl_ext_EXT_blend_equation_separate = sfogl_LOAD_FAILED;
|
||||
int sfogl_ext_EXT_framebuffer_object = sfogl_LOAD_FAILED;
|
||||
int sfogl_ext_ARB_geometry_shader4 = sfogl_LOAD_FAILED;
|
||||
|
||||
void (GL_FUNCPTR *sf_ptrc_glBlendEquationEXT)(GLenum) = NULL;
|
||||
|
||||
|
@ -798,6 +799,34 @@ static int Load_EXT_framebuffer_object()
|
|||
return numFailed;
|
||||
}
|
||||
|
||||
void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureARB)(GLenum, GLenum, GLuint, GLint) = NULL;
|
||||
void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureFaceARB)(GLenum, GLenum, GLuint, GLint, GLenum) = NULL;
|
||||
void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureLayerARB)(GLenum, GLenum, GLuint, GLint, GLint) = NULL;
|
||||
void (GL_FUNCPTR *sf_ptrc_glProgramParameteriARB)(GLuint, GLenum, GLint) = NULL;
|
||||
|
||||
static int Load_ARB_geometry_shader4()
|
||||
{
|
||||
int numFailed = 0;
|
||||
|
||||
sf_ptrc_glFramebufferTextureARB = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLenum, GLuint, GLint)>(glLoaderGetProcAddress("glFramebufferTextureARB"));
|
||||
if (!sf_ptrc_glFramebufferTextureARB)
|
||||
numFailed++;
|
||||
|
||||
sf_ptrc_glFramebufferTextureFaceARB = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLenum, GLuint, GLint, GLenum)>(glLoaderGetProcAddress("glFramebufferTextureFaceARB"));
|
||||
if (!sf_ptrc_glFramebufferTextureFaceARB)
|
||||
numFailed++;
|
||||
|
||||
sf_ptrc_glFramebufferTextureLayerARB = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLenum, GLuint, GLint, GLint)>(glLoaderGetProcAddress("glFramebufferTextureLayerARB"));
|
||||
if (!sf_ptrc_glFramebufferTextureLayerARB)
|
||||
numFailed++;
|
||||
|
||||
sf_ptrc_glProgramParameteriARB = reinterpret_cast<void (GL_FUNCPTR *)(GLuint, GLenum, GLint)>(glLoaderGetProcAddress("glProgramParameteriARB"));
|
||||
if (!sf_ptrc_glProgramParameteriARB)
|
||||
numFailed++;
|
||||
|
||||
return numFailed;
|
||||
}
|
||||
|
||||
typedef int (*PFN_LOADFUNCPOINTERS)();
|
||||
typedef struct sfogl_StrToExtMap_s
|
||||
{
|
||||
|
@ -806,7 +835,7 @@ typedef struct sfogl_StrToExtMap_s
|
|||
PFN_LOADFUNCPOINTERS LoadExtension;
|
||||
} sfogl_StrToExtMap;
|
||||
|
||||
static sfogl_StrToExtMap ExtensionMap[13] = {
|
||||
static sfogl_StrToExtMap ExtensionMap[14] = {
|
||||
{"GL_SGIS_texture_edge_clamp", &sfogl_ext_SGIS_texture_edge_clamp, NULL},
|
||||
{"GL_EXT_texture_edge_clamp", &sfogl_ext_EXT_texture_edge_clamp, NULL},
|
||||
{"GL_EXT_blend_minmax", &sfogl_ext_EXT_blend_minmax, Load_EXT_blend_minmax},
|
||||
|
@ -819,10 +848,11 @@ static sfogl_StrToExtMap ExtensionMap[13] = {
|
|||
{"GL_ARB_fragment_shader", &sfogl_ext_ARB_fragment_shader, NULL},
|
||||
{"GL_ARB_texture_non_power_of_two", &sfogl_ext_ARB_texture_non_power_of_two, NULL},
|
||||
{"GL_EXT_blend_equation_separate", &sfogl_ext_EXT_blend_equation_separate, Load_EXT_blend_equation_separate},
|
||||
{"GL_EXT_framebuffer_object", &sfogl_ext_EXT_framebuffer_object, Load_EXT_framebuffer_object}
|
||||
{"GL_EXT_framebuffer_object", &sfogl_ext_EXT_framebuffer_object, Load_EXT_framebuffer_object},
|
||||
{"GL_ARB_geometry_shader4", &sfogl_ext_ARB_geometry_shader4, Load_ARB_geometry_shader4}
|
||||
};
|
||||
|
||||
static int g_extensionMapSize = 13;
|
||||
static int g_extensionMapSize = 14;
|
||||
|
||||
|
||||
static void ClearExtensionVars()
|
||||
|
@ -840,6 +870,7 @@ static void ClearExtensionVars()
|
|||
sfogl_ext_ARB_texture_non_power_of_two = sfogl_LOAD_FAILED;
|
||||
sfogl_ext_EXT_blend_equation_separate = sfogl_LOAD_FAILED;
|
||||
sfogl_ext_EXT_framebuffer_object = sfogl_LOAD_FAILED;
|
||||
sfogl_ext_ARB_geometry_shader4 = sfogl_LOAD_FAILED;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -183,6 +183,7 @@ extern int sfogl_ext_ARB_fragment_shader;
|
|||
extern int sfogl_ext_ARB_texture_non_power_of_two;
|
||||
extern int sfogl_ext_EXT_blend_equation_separate;
|
||||
extern int sfogl_ext_EXT_framebuffer_object;
|
||||
extern int sfogl_ext_ARB_geometry_shader4;
|
||||
|
||||
#define GL_CLAMP_TO_EDGE_SGIS 0x812F
|
||||
|
||||
|
@ -360,6 +361,27 @@ extern int sfogl_ext_EXT_framebuffer_object;
|
|||
#define GL_STENCIL_INDEX4_EXT 0x8D47
|
||||
#define GL_STENCIL_INDEX8_EXT 0x8D48
|
||||
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8
|
||||
#define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB
|
||||
#define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC
|
||||
#define GL_GEOMETRY_SHADER_ARB 0x8DD9
|
||||
#define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA
|
||||
#define GL_LINES_ADJACENCY_ARB 0x000A
|
||||
#define GL_LINE_STRIP_ADJACENCY_ARB 0x000B
|
||||
#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0
|
||||
#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29
|
||||
#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1
|
||||
#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF
|
||||
#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD
|
||||
#define GL_MAX_VARYING_COMPONENTS 0x8B4B
|
||||
#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE
|
||||
#define GL_PROGRAM_POINT_SIZE_ARB 0x8642
|
||||
#define GL_TRIANGLES_ADJACENCY_ARB 0x000C
|
||||
#define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0x000D
|
||||
|
||||
#define GL_2D 0x0600
|
||||
#define GL_2_BYTES 0x1407
|
||||
#define GL_3D 0x0601
|
||||
|
@ -1201,6 +1223,18 @@ extern void (GL_FUNCPTR *sf_ptrc_glRenderbufferStorageEXT)(GLenum, GLenum, GLsiz
|
|||
#define glRenderbufferStorageEXT sf_ptrc_glRenderbufferStorageEXT
|
||||
#endif // GL_EXT_framebuffer_object
|
||||
|
||||
#ifndef GL_ARB_geometry_shader4
|
||||
#define GL_ARB_geometry_shader4 1
|
||||
extern void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureARB)(GLenum, GLenum, GLuint, GLint);
|
||||
#define glFramebufferTextureARB sf_ptrc_glFramebufferTextureARB
|
||||
extern void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureFaceARB)(GLenum, GLenum, GLuint, GLint, GLenum);
|
||||
#define glFramebufferTextureFaceARB sf_ptrc_glFramebufferTextureFaceARB
|
||||
extern void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureLayerARB)(GLenum, GLenum, GLuint, GLint, GLint);
|
||||
#define glFramebufferTextureLayerARB sf_ptrc_glFramebufferTextureLayerARB
|
||||
extern void (GL_FUNCPTR *sf_ptrc_glProgramParameteriARB)(GLuint, GLenum, GLint);
|
||||
#define glProgramParameteriARB sf_ptrc_glProgramParameteriARB
|
||||
#endif // GL_ARB_geometry_shader4
|
||||
|
||||
GLAPI void APIENTRY glAccum(GLenum, GLfloat);
|
||||
GLAPI void APIENTRY glAlphaFunc(GLenum, GLfloat);
|
||||
GLAPI void APIENTRY glBegin(GLenum);
|
||||
|
|
|
@ -148,6 +148,20 @@ namespace
|
|||
|
||||
return available;
|
||||
}
|
||||
bool checkGeometryShadersAvailable()
|
||||
{
|
||||
// Create a temporary context in case the user checks
|
||||
// before a GlResource is created, thus initializing
|
||||
// the shared context
|
||||
sf::Context context;
|
||||
|
||||
// Make sure that extensions are initialized
|
||||
sf::priv::ensureExtensionsInit();
|
||||
|
||||
bool available = checkShadersAvailable() && GLEXT_geometry_shader4;
|
||||
|
||||
return available;
|
||||
}
|
||||
|
||||
// Transforms an array of 2D vectors into a contiguous array of scalars
|
||||
template <typename T>
|
||||
|
@ -285,9 +299,11 @@ bool Shader::loadFromFile(const std::string& filename, Type type)
|
|||
|
||||
// Compile the shader program
|
||||
if (type == Vertex)
|
||||
return compile(&shader[0], NULL);
|
||||
return compile(&shader[0], NULL, NULL);
|
||||
else if (type == Geometry)
|
||||
return compile(NULL, &shader[0], NULL);
|
||||
else
|
||||
return compile(NULL, &shader[0]);
|
||||
return compile(NULL, NULL, &shader[0]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -311,7 +327,39 @@ bool Shader::loadFromFile(const std::string& vertexShaderFilename, const std::st
|
|||
}
|
||||
|
||||
// Compile the shader program
|
||||
return compile(&vertexShader[0], &fragmentShader[0]);
|
||||
return compile(&vertexShader[0], NULL, &fragmentShader[0]);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Shader::loadFromFile(const std::string& vertexShaderFilename, const std::string& geometryShaderFilename, const std::string& fragmentShaderFilename)
|
||||
{
|
||||
// Read the vertex shader file
|
||||
std::vector<char> vertexShader;
|
||||
if (!getFileContents(vertexShaderFilename, vertexShader))
|
||||
{
|
||||
err() << "Failed to open vertex shader file \"" << vertexShaderFilename << "\"" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the geometry shader file
|
||||
std::vector<char> geometryShader;
|
||||
if (!getFileContents(geometryShaderFilename, geometryShader))
|
||||
{
|
||||
err() << "Failed to open geometry shader file \"" << geometryShaderFilename << "\"" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the fragment shader file
|
||||
std::vector<char> fragmentShader;
|
||||
if (!getFileContents(fragmentShaderFilename, fragmentShader))
|
||||
{
|
||||
err() << "Failed to open fragment shader file \"" << fragmentShaderFilename << "\"" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compile the shader program
|
||||
return compile(&vertexShader[0], &geometryShader[0], &fragmentShader[0]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -320,9 +368,11 @@ bool Shader::loadFromMemory(const std::string& shader, Type type)
|
|||
{
|
||||
// Compile the shader program
|
||||
if (type == Vertex)
|
||||
return compile(shader.c_str(), NULL);
|
||||
return compile(shader.c_str(), NULL, NULL);
|
||||
else if (type == Geometry)
|
||||
return compile(NULL, shader.c_str(), NULL);
|
||||
else
|
||||
return compile(NULL, shader.c_str());
|
||||
return compile(NULL, NULL, shader.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
@ -330,7 +380,15 @@ bool Shader::loadFromMemory(const std::string& shader, Type type)
|
|||
bool Shader::loadFromMemory(const std::string& vertexShader, const std::string& fragmentShader)
|
||||
{
|
||||
// Compile the shader program
|
||||
return compile(vertexShader.c_str(), fragmentShader.c_str());
|
||||
return compile(vertexShader.c_str(), NULL, fragmentShader.c_str());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Shader::loadFromMemory(const std::string& vertexShader, const std::string& geometryShader, const std::string& fragmentShader)
|
||||
{
|
||||
// Compile the shader program
|
||||
return compile(vertexShader.c_str(), geometryShader.c_str(), fragmentShader.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
@ -347,9 +405,11 @@ bool Shader::loadFromStream(InputStream& stream, Type type)
|
|||
|
||||
// Compile the shader program
|
||||
if (type == Vertex)
|
||||
return compile(&shader[0], NULL);
|
||||
return compile(&shader[0], NULL, NULL);
|
||||
else if (type == Geometry)
|
||||
return compile(NULL, &shader[0], NULL);
|
||||
else
|
||||
return compile(NULL, &shader[0]);
|
||||
return compile(NULL, NULL, &shader[0]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -373,7 +433,39 @@ bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& fragme
|
|||
}
|
||||
|
||||
// Compile the shader program
|
||||
return compile(&vertexShader[0], &fragmentShader[0]);
|
||||
return compile(&vertexShader[0], NULL, &fragmentShader[0]);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& geometryShaderStream, InputStream& fragmentShaderStream)
|
||||
{
|
||||
// Read the vertex shader code from the stream
|
||||
std::vector<char> vertexShader;
|
||||
if (!getStreamContents(vertexShaderStream, vertexShader))
|
||||
{
|
||||
err() << "Failed to read vertex shader from stream" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the geometry shader code from the stream
|
||||
std::vector<char> geometryShader;
|
||||
if (!getStreamContents(geometryShaderStream, geometryShader))
|
||||
{
|
||||
err() << "Failed to read geometry shader from stream" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the fragment shader code from the stream
|
||||
std::vector<char> fragmentShader;
|
||||
if (!getStreamContents(fragmentShaderStream, fragmentShader))
|
||||
{
|
||||
err() << "Failed to read fragment shader from stream" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compile the shader program
|
||||
return compile(&vertexShader[0], &geometryShader[0], &fragmentShader[0]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -738,7 +830,19 @@ bool Shader::isAvailable()
|
|||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Shader::compile(const char* vertexShaderCode, const char* fragmentShaderCode)
|
||||
bool Shader::isGeometryAvailable()
|
||||
{
|
||||
// TODO: Remove this lock when it becomes unnecessary in C++11
|
||||
Lock lock(mutex);
|
||||
|
||||
static bool available = checkGeometryShadersAvailable();
|
||||
|
||||
return available;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Shader::compile(const char* vertexShaderCode, const char* geometryShaderCode, const char* fragmentShaderCode)
|
||||
{
|
||||
ensureGlContext();
|
||||
|
||||
|
@ -750,6 +854,14 @@ bool Shader::compile(const char* vertexShaderCode, const char* fragmentShaderCod
|
|||
return false;
|
||||
}
|
||||
|
||||
// Make sure we can use geometry shaders
|
||||
if (geometryShaderCode && !isGeometryAvailable())
|
||||
{
|
||||
err() << "Failed to create a shader: your system doesn't support geometry shaders "
|
||||
<< "(you should test Shader::isGeometryAvailable() before trying to use geometry shaders)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Destroy the shader if it was already created
|
||||
if (m_shaderProgram)
|
||||
{
|
||||
|
@ -794,6 +906,33 @@ bool Shader::compile(const char* vertexShaderCode, const char* fragmentShaderCod
|
|||
glCheck(GLEXT_glDeleteObject(vertexShader));
|
||||
}
|
||||
|
||||
// Create the geometry shader if needed
|
||||
if (geometryShaderCode)
|
||||
{
|
||||
// Create and compile the shader
|
||||
GLEXT_GLhandle geometryShader = GLEXT_glCreateShaderObject(GLEXT_GL_GEOMETRY_SHADER);
|
||||
glCheck(GLEXT_glShaderSource(geometryShader, 1, &geometryShaderCode, NULL));
|
||||
glCheck(GLEXT_glCompileShader(geometryShader));
|
||||
|
||||
// Check the compile log
|
||||
GLint success;
|
||||
glCheck(GLEXT_glGetObjectParameteriv(geometryShader, GLEXT_GL_OBJECT_COMPILE_STATUS, &success));
|
||||
if (success == GL_FALSE)
|
||||
{
|
||||
char log[1024];
|
||||
glCheck(GLEXT_glGetInfoLog(geometryShader, sizeof(log), 0, log));
|
||||
err() << "Failed to compile geometry shader:" << std::endl
|
||||
<< log << std::endl;
|
||||
glCheck(GLEXT_glDeleteObject(geometryShader));
|
||||
glCheck(GLEXT_glDeleteObject(shaderProgram));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Attach the shader to the program, and delete it (not needed anymore)
|
||||
glCheck(GLEXT_glAttachObject(shaderProgram, geometryShader));
|
||||
glCheck(GLEXT_glDeleteObject(geometryShader));
|
||||
}
|
||||
|
||||
// Create the fragment shader if needed
|
||||
if (fragmentShaderCode)
|
||||
{
|
||||
|
@ -929,6 +1068,13 @@ bool Shader::loadFromFile(const std::string& vertexShaderFilename, const std::st
|
|||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Shader::loadFromFile(const std::string& vertexShaderFilename, const std::string& geometryShaderFilename, const std::string& fragmentShaderFilename)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Shader::loadFromMemory(const std::string& shader, Type type)
|
||||
{
|
||||
|
@ -943,6 +1089,13 @@ bool Shader::loadFromMemory(const std::string& vertexShader, const std::string&
|
|||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Shader::loadFromMemory(const std::string& vertexShader, const std::string& geometryShader, const std::string& fragmentShader)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Shader::loadFromStream(InputStream& stream, Type type)
|
||||
{
|
||||
|
@ -957,6 +1110,13 @@ bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& fragme
|
|||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& geometryShaderStream, InputStream& fragmentShaderStream)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shader::setUniform(const std::string& name, float x)
|
||||
{
|
||||
|
@ -1170,7 +1330,14 @@ bool Shader::isAvailable()
|
|||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Shader::compile(const char* vertexShaderCode, const char* fragmentShaderCode)
|
||||
bool Shader::isGeometryAvailable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Shader::compile(const char* vertexShaderCode, const char* geometryShaderCode, const char* fragmentShaderCode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue