Changeset View
Changeset View
Standalone View
Standalone View
source/graphics/ShaderProgram.cpp
Show All 37 Lines | CShaderProgramARB(const VfsPath& vertexFile, const VfsPath& fragmentFile, | ||||
const CShaderDefines& defines, | const CShaderDefines& defines, | ||||
const std::map<CStrIntern, int>& vertexIndexes, const std::map<CStrIntern, frag_index_pair_t>& fragmentIndexes, | const std::map<CStrIntern, int>& vertexIndexes, const std::map<CStrIntern, frag_index_pair_t>& fragmentIndexes, | ||||
int streamflags) : | int streamflags) : | ||||
CShaderProgram(streamflags), | CShaderProgram(streamflags), | ||||
m_VertexFile(vertexFile), m_FragmentFile(fragmentFile), | m_VertexFile(vertexFile), m_FragmentFile(fragmentFile), | ||||
m_Defines(defines), | m_Defines(defines), | ||||
m_VertexIndexes(vertexIndexes), m_FragmentIndexes(fragmentIndexes) | m_VertexIndexes(vertexIndexes), m_FragmentIndexes(fragmentIndexes) | ||||
{ | { | ||||
pglGenProgramsARB(1, &m_VertexProgram); | glGenProgramsARB(1, &m_VertexProgram); | ||||
pglGenProgramsARB(1, &m_FragmentProgram); | glGenProgramsARB(1, &m_FragmentProgram); | ||||
} | } | ||||
~CShaderProgramARB() | ~CShaderProgramARB() | ||||
{ | { | ||||
Unload(); | Unload(); | ||||
pglDeleteProgramsARB(1, &m_VertexProgram); | glDeleteProgramsARB(1, &m_VertexProgram); | ||||
pglDeleteProgramsARB(1, &m_FragmentProgram); | glDeleteProgramsARB(1, &m_FragmentProgram); | ||||
} | } | ||||
bool Compile(GLuint target, const char* targetName, GLuint program, const VfsPath& file, const CStr& code) | bool Compile(GLuint target, const char* targetName, GLuint program, const VfsPath& file, const CStr& code) | ||||
{ | { | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
pglBindProgramARB(target, program); | glBindProgramARB(target, program); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
pglProgramStringARB(target, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)code.length(), code.c_str()); | glProgramStringARB(target, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)code.length(), code.c_str()); | ||||
if (ogl_SquelchError(GL_INVALID_OPERATION)) | if (ogl_SquelchError(GL_INVALID_OPERATION)) | ||||
{ | { | ||||
GLint errPos = 0; | GLint errPos = 0; | ||||
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos); | glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos); | ||||
int errLine = std::count(code.begin(), code.begin() + std::min((int)code.length(), errPos + 1), '\n') + 1; | int errLine = std::count(code.begin(), code.begin() + std::min((int)code.length(), errPos + 1), '\n') + 1; | ||||
char* errStr = (char*)glGetString(GL_PROGRAM_ERROR_STRING_ARB); | char* errStr = (char*)glGetString(GL_PROGRAM_ERROR_STRING_ARB); | ||||
LOGERROR("Failed to compile %s program '%s' (line %d):\n%s", targetName, file.string8(), errLine, errStr); | LOGERROR("Failed to compile %s program '%s' (line %d):\n%s", targetName, file.string8(), errLine, errStr); | ||||
return false; | return false; | ||||
} | } | ||||
pglBindProgramARB(target, 0); | glBindProgramARB(target, 0); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
return true; | return true; | ||||
} | } | ||||
virtual void Reload() | virtual void Reload() | ||||
{ | { | ||||
Show All 29 Lines | // printf(">>>\n%s<<<\n", fragmentCode.c_str()); | ||||
{ | { | ||||
m_IsValid = false; | m_IsValid = false; | ||||
} | } | ||||
virtual void Bind() | virtual void Bind() | ||||
{ | { | ||||
glEnable(GL_VERTEX_PROGRAM_ARB); | glEnable(GL_VERTEX_PROGRAM_ARB); | ||||
glEnable(GL_FRAGMENT_PROGRAM_ARB); | glEnable(GL_FRAGMENT_PROGRAM_ARB); | ||||
pglBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_VertexProgram); | glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_VertexProgram); | ||||
pglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_FragmentProgram); | glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_FragmentProgram); | ||||
BindClientStates(); | BindClientStates(); | ||||
} | } | ||||
virtual void Unbind() | virtual void Unbind() | ||||
{ | { | ||||
glDisable(GL_VERTEX_PROGRAM_ARB); | glDisable(GL_VERTEX_PROGRAM_ARB); | ||||
glDisable(GL_FRAGMENT_PROGRAM_ARB); | glDisable(GL_FRAGMENT_PROGRAM_ARB); | ||||
pglBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0); | glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0); | ||||
pglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0); | glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0); | ||||
UnbindClientStates(); | UnbindClientStates(); | ||||
// TODO: should unbind textures, probably | // TODO: should unbind textures, probably | ||||
} | } | ||||
int GetUniformVertexIndex(CStrIntern id) | int GetUniformVertexIndex(CStrIntern id) | ||||
{ | { | ||||
Show All 24 Lines | // printf(">>>\n%s<<<\n", fragmentCode.c_str()); | ||||
virtual void BindTexture(texture_id_t id, Handle tex) | virtual void BindTexture(texture_id_t id, Handle tex) | ||||
{ | { | ||||
frag_index_pair_t fPair = GetUniformFragmentIndex(id); | frag_index_pair_t fPair = GetUniformFragmentIndex(id); | ||||
int index = fPair.first; | int index = fPair.first; | ||||
if (index != -1) | if (index != -1) | ||||
{ | { | ||||
GLuint h; | GLuint h; | ||||
ogl_tex_get_texture_id(tex, &h); | ogl_tex_get_texture_id(tex, &h); | ||||
pglActiveTextureARB(GL_TEXTURE0+index); | glActiveTextureARB(GL_TEXTURE0+index); | ||||
glBindTexture(fPair.second, h); | glBindTexture(fPair.second, h); | ||||
} | } | ||||
} | } | ||||
virtual void BindTexture(texture_id_t id, GLuint tex) | virtual void BindTexture(texture_id_t id, GLuint tex) | ||||
{ | { | ||||
frag_index_pair_t fPair = GetUniformFragmentIndex(id); | frag_index_pair_t fPair = GetUniformFragmentIndex(id); | ||||
int index = fPair.first; | int index = fPair.first; | ||||
if (index != -1) | if (index != -1) | ||||
{ | { | ||||
pglActiveTextureARB(GL_TEXTURE0+index); | glActiveTextureARB(GL_TEXTURE0+index); | ||||
glBindTexture(fPair.second, tex); | glBindTexture(fPair.second, tex); | ||||
} | } | ||||
} | } | ||||
virtual void BindTexture(Binding id, Handle tex) | virtual void BindTexture(Binding id, Handle tex) | ||||
{ | { | ||||
int index = id.second; | int index = id.second; | ||||
if (index != -1) | if (index != -1) | ||||
ogl_tex_bind(tex, index); | ogl_tex_bind(tex, index); | ||||
} | } | ||||
virtual Binding GetUniformBinding(uniform_id_t id) | virtual Binding GetUniformBinding(uniform_id_t id) | ||||
{ | { | ||||
return Binding(GetUniformVertexIndex(id), GetUniformFragmentIndex(id).first); | return Binding(GetUniformVertexIndex(id), GetUniformFragmentIndex(id).first); | ||||
} | } | ||||
virtual void Uniform(Binding id, float v0, float v1, float v2, float v3) | virtual void Uniform(Binding id, float v0, float v1, float v2, float v3) | ||||
{ | { | ||||
if (id.first != -1) | if (id.first != -1) | ||||
pglProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first, v0, v1, v2, v3); | glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first, v0, v1, v2, v3); | ||||
if (id.second != -1) | if (id.second != -1) | ||||
pglProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second, v0, v1, v2, v3); | glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second, v0, v1, v2, v3); | ||||
} | } | ||||
virtual void Uniform(Binding id, const CMatrix3D& v) | virtual void Uniform(Binding id, const CMatrix3D& v) | ||||
{ | { | ||||
if (id.first != -1) | if (id.first != -1) | ||||
{ | { | ||||
pglProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first+0, v._11, v._12, v._13, v._14); | glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first+0, v._11, v._12, v._13, v._14); | ||||
pglProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first+1, v._21, v._22, v._23, v._24); | glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first+1, v._21, v._22, v._23, v._24); | ||||
pglProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first+2, v._31, v._32, v._33, v._34); | glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first+2, v._31, v._32, v._33, v._34); | ||||
pglProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first+3, v._41, v._42, v._43, v._44); | glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first+3, v._41, v._42, v._43, v._44); | ||||
} | } | ||||
if (id.second != -1) | if (id.second != -1) | ||||
{ | { | ||||
pglProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second+0, v._11, v._12, v._13, v._14); | glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second+0, v._11, v._12, v._13, v._14); | ||||
pglProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second+1, v._21, v._22, v._23, v._24); | glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second+1, v._21, v._22, v._23, v._24); | ||||
pglProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second+2, v._31, v._32, v._33, v._34); | glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second+2, v._31, v._32, v._33, v._34); | ||||
pglProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second+3, v._41, v._42, v._43, v._44); | glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second+3, v._41, v._42, v._43, v._44); | ||||
} | } | ||||
} | } | ||||
virtual void Uniform(Binding id, size_t count, const CMatrix3D* v) | virtual void Uniform(Binding id, size_t count, const CMatrix3D* v) | ||||
{ | { | ||||
ENSURE(count == 1); | ENSURE(count == 1); | ||||
Uniform(id, v[0]); | Uniform(id, v[0]); | ||||
} | } | ||||
Show All 27 Lines | CShaderProgramGLSL(const VfsPath& vertexFile, const VfsPath& fragmentFile, | ||||
const std::map<CStrIntern, int>& vertexAttribs, | const std::map<CStrIntern, int>& vertexAttribs, | ||||
int streamflags) : | int streamflags) : | ||||
CShaderProgram(streamflags), | CShaderProgram(streamflags), | ||||
m_VertexFile(vertexFile), m_FragmentFile(fragmentFile), | m_VertexFile(vertexFile), m_FragmentFile(fragmentFile), | ||||
m_Defines(defines), | m_Defines(defines), | ||||
m_VertexAttribs(vertexAttribs) | m_VertexAttribs(vertexAttribs) | ||||
{ | { | ||||
m_Program = 0; | m_Program = 0; | ||||
m_VertexShader = pglCreateShaderObjectARB(GL_VERTEX_SHADER); | m_VertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER); | ||||
m_FragmentShader = pglCreateShaderObjectARB(GL_FRAGMENT_SHADER); | m_FragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER); | ||||
} | } | ||||
~CShaderProgramGLSL() | ~CShaderProgramGLSL() | ||||
{ | { | ||||
Unload(); | Unload(); | ||||
pglDeleteShader(m_VertexShader); | glDeleteShader(m_VertexShader); | ||||
pglDeleteShader(m_FragmentShader); | glDeleteShader(m_FragmentShader); | ||||
} | } | ||||
bool Compile(GLhandleARB shader, const VfsPath& file, const CStr& code) | bool Compile(GLhandleARB shader, const VfsPath& file, const CStr& code) | ||||
{ | { | ||||
TIMER_ACCRUE(tc_ShaderGLSLCompile); | TIMER_ACCRUE(tc_ShaderGLSLCompile); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
const char* code_string = code.c_str(); | const char* code_string = code.c_str(); | ||||
GLint code_length = code.length(); | GLint code_length = code.length(); | ||||
pglShaderSourceARB(shader, 1, &code_string, &code_length); | glShaderSourceARB(shader, 1, &code_string, &code_length); | ||||
pglCompileShaderARB(shader); | glCompileShaderARB(shader); | ||||
GLint ok = 0; | GLint ok = 0; | ||||
pglGetShaderiv(shader, GL_COMPILE_STATUS, &ok); | glGetShaderiv(shader, GL_COMPILE_STATUS, &ok); | ||||
GLint length = 0; | GLint length = 0; | ||||
pglGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); | ||||
// Apparently sometimes GL_INFO_LOG_LENGTH is incorrectly reported as 0 | // Apparently sometimes GL_INFO_LOG_LENGTH is incorrectly reported as 0 | ||||
// (http://code.google.com/p/android/issues/detail?id=9953) | // (http://code.google.com/p/android/issues/detail?id=9953) | ||||
if (!ok && length == 0) | if (!ok && length == 0) | ||||
length = 4096; | length = 4096; | ||||
if (length > 1) | if (length > 1) | ||||
{ | { | ||||
char* infolog = new char[length]; | char* infolog = new char[length]; | ||||
pglGetShaderInfoLog(shader, length, NULL, infolog); | glGetShaderInfoLog(shader, length, NULL, infolog); | ||||
if (ok) | if (ok) | ||||
LOGMESSAGE("Info when compiling shader '%s':\n%s", file.string8(), infolog); | LOGMESSAGE("Info when compiling shader '%s':\n%s", file.string8(), infolog); | ||||
else | else | ||||
LOGERROR("Failed to compile shader '%s':\n%s", file.string8(), infolog); | LOGERROR("Failed to compile shader '%s':\n%s", file.string8(), infolog); | ||||
delete[] infolog; | delete[] infolog; | ||||
} | } | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
return (ok ? true : false); | return (ok ? true : false); | ||||
} | } | ||||
bool Link() | bool Link() | ||||
{ | { | ||||
TIMER_ACCRUE(tc_ShaderGLSLLink); | TIMER_ACCRUE(tc_ShaderGLSLLink); | ||||
ENSURE(!m_Program); | ENSURE(!m_Program); | ||||
m_Program = pglCreateProgramObjectARB(); | m_Program = glCreateProgramObjectARB(); | ||||
pglAttachObjectARB(m_Program, m_VertexShader); | glAttachObjectARB(m_Program, m_VertexShader); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
pglAttachObjectARB(m_Program, m_FragmentShader); | glAttachObjectARB(m_Program, m_FragmentShader); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
// Set up the attribute bindings explicitly, since apparently drivers | // Set up the attribute bindings explicitly, since apparently drivers | ||||
// don't always pick the most efficient bindings automatically, | // don't always pick the most efficient bindings automatically, | ||||
// and also this lets us hardcode indexes into VertexPointer etc | // and also this lets us hardcode indexes into VertexPointer etc | ||||
for (std::map<CStrIntern, int>::iterator it = m_VertexAttribs.begin(); it != m_VertexAttribs.end(); ++it) | for (std::map<CStrIntern, int>::iterator it = m_VertexAttribs.begin(); it != m_VertexAttribs.end(); ++it) | ||||
pglBindAttribLocationARB(m_Program, it->second, it->first.c_str()); | glBindAttribLocationARB(m_Program, it->second, it->first.c_str()); | ||||
pglLinkProgramARB(m_Program); | glLinkProgramARB(m_Program); | ||||
GLint ok = 0; | GLint ok = 0; | ||||
pglGetProgramiv(m_Program, GL_LINK_STATUS, &ok); | glGetProgramiv(m_Program, GL_LINK_STATUS, &ok); | ||||
GLint length = 0; | GLint length = 0; | ||||
pglGetProgramiv(m_Program, GL_INFO_LOG_LENGTH, &length); | glGetProgramiv(m_Program, GL_INFO_LOG_LENGTH, &length); | ||||
if (!ok && length == 0) | if (!ok && length == 0) | ||||
length = 4096; | length = 4096; | ||||
if (length > 1) | if (length > 1) | ||||
{ | { | ||||
char* infolog = new char[length]; | char* infolog = new char[length]; | ||||
pglGetProgramInfoLog(m_Program, length, NULL, infolog); | glGetProgramInfoLog(m_Program, length, NULL, infolog); | ||||
if (ok) | if (ok) | ||||
LOGMESSAGE("Info when linking program '%s'+'%s':\n%s", m_VertexFile.string8(), m_FragmentFile.string8(), infolog); | LOGMESSAGE("Info when linking program '%s'+'%s':\n%s", m_VertexFile.string8(), m_FragmentFile.string8(), infolog); | ||||
else | else | ||||
LOGERROR("Failed to link program '%s'+'%s':\n%s", m_VertexFile.string8(), m_FragmentFile.string8(), infolog); | LOGERROR("Failed to link program '%s'+'%s':\n%s", m_VertexFile.string8(), m_FragmentFile.string8(), infolog); | ||||
delete[] infolog; | delete[] infolog; | ||||
} | } | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
if (!ok) | if (!ok) | ||||
return false; | return false; | ||||
m_Uniforms.clear(); | m_Uniforms.clear(); | ||||
m_Samplers.clear(); | m_Samplers.clear(); | ||||
Bind(); | Bind(); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
GLint numUniforms = 0; | GLint numUniforms = 0; | ||||
pglGetProgramiv(m_Program, GL_ACTIVE_UNIFORMS, &numUniforms); | glGetProgramiv(m_Program, GL_ACTIVE_UNIFORMS, &numUniforms); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
for (GLint i = 0; i < numUniforms; ++i) | for (GLint i = 0; i < numUniforms; ++i) | ||||
{ | { | ||||
char name[256] = {0}; | char name[256] = {0}; | ||||
GLsizei nameLength = 0; | GLsizei nameLength = 0; | ||||
GLint size = 0; | GLint size = 0; | ||||
GLenum type = 0; | GLenum type = 0; | ||||
pglGetActiveUniformARB(m_Program, i, ARRAY_SIZE(name), &nameLength, &size, &type, name); | glGetActiveUniformARB(m_Program, i, ARRAY_SIZE(name), &nameLength, &size, &type, name); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
GLint loc = pglGetUniformLocationARB(m_Program, name); | GLint loc = glGetUniformLocationARB(m_Program, name); | ||||
CStrIntern nameIntern(name); | CStrIntern nameIntern(name); | ||||
m_Uniforms[nameIntern] = std::make_pair(loc, type); | m_Uniforms[nameIntern] = std::make_pair(loc, type); | ||||
// Assign sampler uniforms to sequential texture units | // Assign sampler uniforms to sequential texture units | ||||
if (type == GL_SAMPLER_2D | if (type == GL_SAMPLER_2D | ||||
|| type == GL_SAMPLER_CUBE | || type == GL_SAMPLER_CUBE | ||||
#if !CONFIG2_GLES | #if !CONFIG2_GLES | ||||
|| type == GL_SAMPLER_2D_SHADOW | || type == GL_SAMPLER_2D_SHADOW | ||||
#endif | #endif | ||||
) | ) | ||||
{ | { | ||||
int unit = (int)m_Samplers.size(); | int unit = (int)m_Samplers.size(); | ||||
m_Samplers[nameIntern].first = (type == GL_SAMPLER_CUBE ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D); | m_Samplers[nameIntern].first = (type == GL_SAMPLER_CUBE ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D); | ||||
m_Samplers[nameIntern].second = unit; | m_Samplers[nameIntern].second = unit; | ||||
pglUniform1iARB(loc, unit); // link uniform to unit | glUniform1iARB(loc, unit); // link uniform to unit | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
} | } | ||||
} | } | ||||
// TODO: verify that we're not using more samplers than is supported | // TODO: verify that we're not using more samplers than is supported | ||||
Unbind(); | Unbind(); | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | #endif | ||||
m_IsValid = true; | m_IsValid = true; | ||||
} | } | ||||
void Unload() | void Unload() | ||||
{ | { | ||||
m_IsValid = false; | m_IsValid = false; | ||||
if (m_Program) | if (m_Program) | ||||
pglDeleteProgram(m_Program); | glDeleteProgram(m_Program); | ||||
m_Program = 0; | m_Program = 0; | ||||
// The shader objects can be reused and don't need to be deleted here | // The shader objects can be reused and don't need to be deleted here | ||||
} | } | ||||
virtual void Bind() | virtual void Bind() | ||||
{ | { | ||||
pglUseProgramObjectARB(m_Program); | glUseProgramObjectARB(m_Program); | ||||
for (std::map<CStrIntern, int>::iterator it = m_VertexAttribs.begin(); it != m_VertexAttribs.end(); ++it) | for (std::map<CStrIntern, int>::iterator it = m_VertexAttribs.begin(); it != m_VertexAttribs.end(); ++it) | ||||
pglEnableVertexAttribArrayARB(it->second); | glEnableVertexAttribArrayARB(it->second); | ||||
} | } | ||||
virtual void Unbind() | virtual void Unbind() | ||||
{ | { | ||||
pglUseProgramObjectARB(0); | glUseProgramObjectARB(0); | ||||
for (std::map<CStrIntern, int>::iterator it = m_VertexAttribs.begin(); it != m_VertexAttribs.end(); ++it) | for (std::map<CStrIntern, int>::iterator it = m_VertexAttribs.begin(); it != m_VertexAttribs.end(); ++it) | ||||
pglDisableVertexAttribArrayARB(it->second); | glDisableVertexAttribArrayARB(it->second); | ||||
// TODO: should unbind textures, probably | // TODO: should unbind textures, probably | ||||
} | } | ||||
virtual Binding GetTextureBinding(texture_id_t id) | virtual Binding GetTextureBinding(texture_id_t id) | ||||
{ | { | ||||
std::map<CStrIntern, std::pair<GLenum, int> >::iterator it = m_Samplers.find(CStrIntern(id)); | std::map<CStrIntern, std::pair<GLenum, int> >::iterator it = m_Samplers.find(CStrIntern(id)); | ||||
if (it == m_Samplers.end()) | if (it == m_Samplers.end()) | ||||
return Binding(); | return Binding(); | ||||
else | else | ||||
return Binding((int)it->second.first, it->second.second); | return Binding((int)it->second.first, it->second.second); | ||||
} | } | ||||
virtual void BindTexture(texture_id_t id, Handle tex) | virtual void BindTexture(texture_id_t id, Handle tex) | ||||
{ | { | ||||
std::map<CStrIntern, std::pair<GLenum, int> >::iterator it = m_Samplers.find(CStrIntern(id)); | std::map<CStrIntern, std::pair<GLenum, int> >::iterator it = m_Samplers.find(CStrIntern(id)); | ||||
if (it == m_Samplers.end()) | if (it == m_Samplers.end()) | ||||
return; | return; | ||||
GLuint h; | GLuint h; | ||||
ogl_tex_get_texture_id(tex, &h); | ogl_tex_get_texture_id(tex, &h); | ||||
pglActiveTextureARB(GL_TEXTURE0 + it->second.second); | glActiveTextureARB(GL_TEXTURE0 + it->second.second); | ||||
glBindTexture(it->second.first, h); | glBindTexture(it->second.first, h); | ||||
} | } | ||||
virtual void BindTexture(texture_id_t id, GLuint tex) | virtual void BindTexture(texture_id_t id, GLuint tex) | ||||
{ | { | ||||
std::map<CStrIntern, std::pair<GLenum, int> >::iterator it = m_Samplers.find(CStrIntern(id)); | std::map<CStrIntern, std::pair<GLenum, int> >::iterator it = m_Samplers.find(CStrIntern(id)); | ||||
if (it == m_Samplers.end()) | if (it == m_Samplers.end()) | ||||
return; | return; | ||||
pglActiveTextureARB(GL_TEXTURE0 + it->second.second); | glActiveTextureARB(GL_TEXTURE0 + it->second.second); | ||||
glBindTexture(it->second.first, tex); | glBindTexture(it->second.first, tex); | ||||
} | } | ||||
virtual void BindTexture(Binding id, Handle tex) | virtual void BindTexture(Binding id, Handle tex) | ||||
{ | { | ||||
if (id.second == -1) | if (id.second == -1) | ||||
return; | return; | ||||
GLuint h; | GLuint h; | ||||
ogl_tex_get_texture_id(tex, &h); | ogl_tex_get_texture_id(tex, &h); | ||||
pglActiveTextureARB(GL_TEXTURE0 + id.second); | glActiveTextureARB(GL_TEXTURE0 + id.second); | ||||
glBindTexture(id.first, h); | glBindTexture(id.first, h); | ||||
} | } | ||||
virtual Binding GetUniformBinding(uniform_id_t id) | virtual Binding GetUniformBinding(uniform_id_t id) | ||||
{ | { | ||||
std::map<CStrIntern, std::pair<int, GLenum> >::iterator it = m_Uniforms.find(id); | std::map<CStrIntern, std::pair<int, GLenum> >::iterator it = m_Uniforms.find(id); | ||||
if (it == m_Uniforms.end()) | if (it == m_Uniforms.end()) | ||||
return Binding(); | return Binding(); | ||||
else | else | ||||
return Binding(it->second.first, (int)it->second.second); | return Binding(it->second.first, (int)it->second.second); | ||||
} | } | ||||
virtual void Uniform(Binding id, float v0, float v1, float v2, float v3) | virtual void Uniform(Binding id, float v0, float v1, float v2, float v3) | ||||
{ | { | ||||
if (id.first != -1) | if (id.first != -1) | ||||
{ | { | ||||
if (id.second == GL_FLOAT) | if (id.second == GL_FLOAT) | ||||
pglUniform1fARB(id.first, v0); | glUniform1fARB(id.first, v0); | ||||
else if (id.second == GL_FLOAT_VEC2) | else if (id.second == GL_FLOAT_VEC2) | ||||
pglUniform2fARB(id.first, v0, v1); | glUniform2fARB(id.first, v0, v1); | ||||
else if (id.second == GL_FLOAT_VEC3) | else if (id.second == GL_FLOAT_VEC3) | ||||
pglUniform3fARB(id.first, v0, v1, v2); | glUniform3fARB(id.first, v0, v1, v2); | ||||
else if (id.second == GL_FLOAT_VEC4) | else if (id.second == GL_FLOAT_VEC4) | ||||
pglUniform4fARB(id.first, v0, v1, v2, v3); | glUniform4fARB(id.first, v0, v1, v2, v3); | ||||
else | else | ||||
LOGERROR("CShaderProgramGLSL::Uniform(): Invalid uniform type (expected float, vec2, vec3, vec4)"); | LOGERROR("CShaderProgramGLSL::Uniform(): Invalid uniform type (expected float, vec2, vec3, vec4)"); | ||||
} | } | ||||
} | } | ||||
virtual void Uniform(Binding id, const CMatrix3D& v) | virtual void Uniform(Binding id, const CMatrix3D& v) | ||||
{ | { | ||||
if (id.first != -1) | if (id.first != -1) | ||||
{ | { | ||||
if (id.second == GL_FLOAT_MAT4) | if (id.second == GL_FLOAT_MAT4) | ||||
pglUniformMatrix4fvARB(id.first, 1, GL_FALSE, &v._11); | glUniformMatrix4fvARB(id.first, 1, GL_FALSE, &v._11); | ||||
else | else | ||||
LOGERROR("CShaderProgramGLSL::Uniform(): Invalid uniform type (expected mat4)"); | LOGERROR("CShaderProgramGLSL::Uniform(): Invalid uniform type (expected mat4)"); | ||||
} | } | ||||
} | } | ||||
virtual void Uniform(Binding id, size_t count, const CMatrix3D* v) | virtual void Uniform(Binding id, size_t count, const CMatrix3D* v) | ||||
{ | { | ||||
if (id.first != -1) | if (id.first != -1) | ||||
{ | { | ||||
if (id.second == GL_FLOAT_MAT4) | if (id.second == GL_FLOAT_MAT4) | ||||
pglUniformMatrix4fvARB(id.first, count, GL_FALSE, &v->_11); | glUniformMatrix4fvARB(id.first, count, GL_FALSE, &v->_11); | ||||
else | else | ||||
LOGERROR("CShaderProgramGLSL::Uniform(): Invalid uniform type (expected mat4)"); | LOGERROR("CShaderProgramGLSL::Uniform(): Invalid uniform type (expected mat4)"); | ||||
} | } | ||||
} | } | ||||
// Map the various fixed-function Pointer functions onto generic vertex attributes | // Map the various fixed-function Pointer functions onto generic vertex attributes | ||||
// (matching the attribute indexes from ShaderManager's ParseAttribSemantics): | // (matching the attribute indexes from ShaderManager's ParseAttribSemantics): | ||||
virtual void VertexPointer(GLint size, GLenum type, GLsizei stride, const void* pointer) | virtual void VertexPointer(GLint size, GLenum type, GLsizei stride, const void* pointer) | ||||
{ | { | ||||
pglVertexAttribPointerARB(0, size, type, GL_FALSE, stride, pointer); | glVertexAttribPointerARB(0, size, type, GL_FALSE, stride, pointer); | ||||
m_ValidStreams |= STREAM_POS; | m_ValidStreams |= STREAM_POS; | ||||
} | } | ||||
virtual void NormalPointer(GLenum type, GLsizei stride, const void* pointer) | virtual void NormalPointer(GLenum type, GLsizei stride, const void* pointer) | ||||
{ | { | ||||
pglVertexAttribPointerARB(2, 3, type, GL_TRUE, stride, pointer); | glVertexAttribPointerARB(2, 3, type, GL_TRUE, stride, pointer); | ||||
m_ValidStreams |= STREAM_NORMAL; | m_ValidStreams |= STREAM_NORMAL; | ||||
} | } | ||||
virtual void ColorPointer(GLint size, GLenum type, GLsizei stride, const void* pointer) | virtual void ColorPointer(GLint size, GLenum type, GLsizei stride, const void* pointer) | ||||
{ | { | ||||
pglVertexAttribPointerARB(3, size, type, GL_TRUE, stride, pointer); | glVertexAttribPointerARB(3, size, type, GL_TRUE, stride, pointer); | ||||
m_ValidStreams |= STREAM_COLOR; | m_ValidStreams |= STREAM_COLOR; | ||||
} | } | ||||
virtual void TexCoordPointer(GLenum texture, GLint size, GLenum type, GLsizei stride, const void* pointer) | virtual void TexCoordPointer(GLenum texture, GLint size, GLenum type, GLsizei stride, const void* pointer) | ||||
{ | { | ||||
pglVertexAttribPointerARB(8 + texture - GL_TEXTURE0, size, type, GL_FALSE, stride, pointer); | glVertexAttribPointerARB(8 + texture - GL_TEXTURE0, size, type, GL_FALSE, stride, pointer); | ||||
m_ValidStreams |= STREAM_UV0 << (texture - GL_TEXTURE0); | m_ValidStreams |= STREAM_UV0 << (texture - GL_TEXTURE0); | ||||
} | } | ||||
virtual void VertexAttribPointer(attrib_id_t id, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer) | virtual void VertexAttribPointer(attrib_id_t id, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer) | ||||
{ | { | ||||
std::map<CStrIntern, int>::iterator it = m_VertexAttribs.find(id); | std::map<CStrIntern, int>::iterator it = m_VertexAttribs.find(id); | ||||
if (it != m_VertexAttribs.end()) | if (it != m_VertexAttribs.end()) | ||||
{ | { | ||||
pglVertexAttribPointerARB(it->second, size, type, normalized, stride, pointer); | glVertexAttribPointerARB(it->second, size, type, normalized, stride, pointer); | ||||
} | } | ||||
} | } | ||||
virtual void VertexAttribIPointer(attrib_id_t id, GLint size, GLenum type, GLsizei stride, const void* pointer) | virtual void VertexAttribIPointer(attrib_id_t id, GLint size, GLenum type, GLsizei stride, const void* pointer) | ||||
{ | { | ||||
std::map<CStrIntern, int>::iterator it = m_VertexAttribs.find(id); | std::map<CStrIntern, int>::iterator it = m_VertexAttribs.find(id); | ||||
if (it != m_VertexAttribs.end()) | if (it != m_VertexAttribs.end()) | ||||
{ | { | ||||
#if CONFIG2_GLES | #if CONFIG2_GLES | ||||
debug_warn(L"glVertexAttribIPointer not supported on GLES"); | debug_warn(L"glVertexAttribIPointer not supported on GLES"); | ||||
#else | #else | ||||
pglVertexAttribIPointerEXT(it->second, size, type, stride, pointer); | glVertexAttribIPointerEXT(it->second, size, type, stride, pointer); | ||||
#endif | #endif | ||||
} | } | ||||
} | } | ||||
private: | private: | ||||
VfsPath m_VertexFile; | VfsPath m_VertexFile; | ||||
VfsPath m_FragmentFile; | VfsPath m_FragmentFile; | ||||
CShaderDefines m_Defines; | CShaderDefines m_Defines; | ||||
▲ Show 20 Lines • Show All 181 Lines • ▼ Show 20 Lines | |||||
void CShaderProgram::ColorPointer(GLint size, GLenum type, GLsizei stride, const void* pointer) | void CShaderProgram::ColorPointer(GLint size, GLenum type, GLsizei stride, const void* pointer) | ||||
{ | { | ||||
glColorPointer(size, type, stride, pointer); | glColorPointer(size, type, stride, pointer); | ||||
m_ValidStreams |= STREAM_COLOR; | m_ValidStreams |= STREAM_COLOR; | ||||
} | } | ||||
void CShaderProgram::TexCoordPointer(GLenum texture, GLint size, GLenum type, GLsizei stride, const void* pointer) | void CShaderProgram::TexCoordPointer(GLenum texture, GLint size, GLenum type, GLsizei stride, const void* pointer) | ||||
{ | { | ||||
pglClientActiveTextureARB(texture); | glClientActiveTextureARB(texture); | ||||
glTexCoordPointer(size, type, stride, pointer); | glTexCoordPointer(size, type, stride, pointer); | ||||
pglClientActiveTextureARB(GL_TEXTURE0); | glClientActiveTextureARB(GL_TEXTURE0); | ||||
m_ValidStreams |= STREAM_UV0 << (texture - GL_TEXTURE0); | m_ValidStreams |= STREAM_UV0 << (texture - GL_TEXTURE0); | ||||
} | } | ||||
void CShaderProgram::BindClientStates() | void CShaderProgram::BindClientStates() | ||||
{ | { | ||||
ENSURE(m_StreamFlags == (m_StreamFlags & (STREAM_POS|STREAM_NORMAL|STREAM_COLOR|STREAM_UV0|STREAM_UV1))); | ENSURE(m_StreamFlags == (m_StreamFlags & (STREAM_POS|STREAM_NORMAL|STREAM_COLOR|STREAM_UV0|STREAM_UV1))); | ||||
// Enable all the desired client states for non-GLSL rendering | // Enable all the desired client states for non-GLSL rendering | ||||
if (m_StreamFlags & STREAM_POS) glEnableClientState(GL_VERTEX_ARRAY); | if (m_StreamFlags & STREAM_POS) glEnableClientState(GL_VERTEX_ARRAY); | ||||
if (m_StreamFlags & STREAM_NORMAL) glEnableClientState(GL_NORMAL_ARRAY); | if (m_StreamFlags & STREAM_NORMAL) glEnableClientState(GL_NORMAL_ARRAY); | ||||
if (m_StreamFlags & STREAM_COLOR) glEnableClientState(GL_COLOR_ARRAY); | if (m_StreamFlags & STREAM_COLOR) glEnableClientState(GL_COLOR_ARRAY); | ||||
if (m_StreamFlags & STREAM_UV0) | if (m_StreamFlags & STREAM_UV0) | ||||
{ | { | ||||
pglClientActiveTextureARB(GL_TEXTURE0); | glClientActiveTextureARB(GL_TEXTURE0); | ||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY); | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | ||||
} | } | ||||
if (m_StreamFlags & STREAM_UV1) | if (m_StreamFlags & STREAM_UV1) | ||||
{ | { | ||||
pglClientActiveTextureARB(GL_TEXTURE1); | glClientActiveTextureARB(GL_TEXTURE1); | ||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY); | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | ||||
pglClientActiveTextureARB(GL_TEXTURE0); | glClientActiveTextureARB(GL_TEXTURE0); | ||||
} | } | ||||
// Rendering code must subsequently call VertexPointer etc for all of the streams | // Rendering code must subsequently call VertexPointer etc for all of the streams | ||||
// that were activated in this function, else AssertPointersBound will complain | // that were activated in this function, else AssertPointersBound will complain | ||||
// that some arrays were unspecified | // that some arrays were unspecified | ||||
m_ValidStreams = 0; | m_ValidStreams = 0; | ||||
} | } | ||||
void CShaderProgram::UnbindClientStates() | void CShaderProgram::UnbindClientStates() | ||||
{ | { | ||||
if (m_StreamFlags & STREAM_POS) glDisableClientState(GL_VERTEX_ARRAY); | if (m_StreamFlags & STREAM_POS) glDisableClientState(GL_VERTEX_ARRAY); | ||||
if (m_StreamFlags & STREAM_NORMAL) glDisableClientState(GL_NORMAL_ARRAY); | if (m_StreamFlags & STREAM_NORMAL) glDisableClientState(GL_NORMAL_ARRAY); | ||||
if (m_StreamFlags & STREAM_COLOR) glDisableClientState(GL_COLOR_ARRAY); | if (m_StreamFlags & STREAM_COLOR) glDisableClientState(GL_COLOR_ARRAY); | ||||
if (m_StreamFlags & STREAM_UV0) | if (m_StreamFlags & STREAM_UV0) | ||||
{ | { | ||||
pglClientActiveTextureARB(GL_TEXTURE0); | glClientActiveTextureARB(GL_TEXTURE0); | ||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY); | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||||
} | } | ||||
if (m_StreamFlags & STREAM_UV1) | if (m_StreamFlags & STREAM_UV1) | ||||
{ | { | ||||
pglClientActiveTextureARB(GL_TEXTURE1); | glClientActiveTextureARB(GL_TEXTURE1); | ||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY); | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||||
pglClientActiveTextureARB(GL_TEXTURE0); | glClientActiveTextureARB(GL_TEXTURE0); | ||||
} | } | ||||
} | } | ||||
#endif // !CONFIG2_GLES | #endif // !CONFIG2_GLES | ||||
void CShaderProgram::AssertPointersBound() | void CShaderProgram::AssertPointersBound() | ||||
{ | { | ||||
ENSURE((m_StreamFlags & ~m_ValidStreams) == 0); | ENSURE((m_StreamFlags & ~m_ValidStreams) == 0); | ||||
} | } |
Wildfire Games · Phabricator