glshaders.cpp Example File
demos/boxes/glshaders.cpp
#include "glshaders.h"
#define GLSHADERS_ASSERT_OPENGL(prefix, assertion, returnStatement) \
if (m_failed || !(assertion)) { \
if (!m_failed) qCritical(prefix ": The necessary OpenGL functions are not available."); \
m_failed = true; \
returnStatement; \
}
GLShader::GLShader(const char *data, int size, GLenum shaderType)
: m_compileError(false), m_failed(false)
{
GLSHADERS_ASSERT_OPENGL("GLShader::GLShader",
glCreateShaderObjectARB && glShaderSourceARB && glCompileShaderARB && glGetObjectParameterivARB, return)
m_shader = glCreateShaderObjectARB(shaderType);
GLint glSize = size;
glShaderSourceARB(m_shader, 1, reinterpret_cast<const GLcharARB**>(&data), &glSize);
glCompileShaderARB(m_shader);
int status;
glGetObjectParameterivARB(m_shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
m_compileError = (status != 1);
}
GLShader::GLShader(const QString& fileName, GLenum shaderType)
: m_compileError(false), m_failed(false)
{
GLSHADERS_ASSERT_OPENGL("GLShader::GLShader",
glCreateShaderObjectARB && glShaderSourceARB && glCompileShaderARB && glGetObjectParameterivARB, return)
m_shader = glCreateShaderObjectARB(shaderType);
QFile file(fileName);
if (file.open(QIODevice::ReadOnly)) {
QByteArray bytes = file.readAll();
GLint size = file.size();
const char *p = bytes.data();
file.close();
glShaderSourceARB(m_shader, 1, reinterpret_cast<const GLcharARB**>(&p), &size);
glCompileShaderARB(m_shader);
int status;
glGetObjectParameterivARB(m_shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
m_compileError = (status != 1);
} else {
m_compileError = true;
}
}
GLShader::~GLShader()
{
GLSHADERS_ASSERT_OPENGL("GLShader::~GLShader", glDeleteObjectARB, return)
glDeleteObjectARB(m_shader);
}
QString GLShader::log()
{
GLSHADERS_ASSERT_OPENGL("GLShader::log", glGetObjectParameterivARB
&& glGetInfoLogARB, return QLatin1String("GLSL not supported."))
int length;
glGetObjectParameterivARB(m_shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
char *log = new char[length + 1];
GLsizei glLength = length;
glGetInfoLogARB(m_shader, glLength, &glLength, reinterpret_cast<GLcharARB*>(log));
log[glLength] = '\0';
QString result(log);
delete log;
return result;
}
GLVertexShader::GLVertexShader(const char *data, int size) : GLShader(data, size, GL_VERTEX_SHADER_ARB)
{
}
GLVertexShader::GLVertexShader(const QString& fileName) : GLShader(fileName, GL_VERTEX_SHADER_ARB)
{
}
GLFragmentShader::GLFragmentShader(const char *data, int size) : GLShader(data, size, GL_FRAGMENT_SHADER_ARB)
{
}
GLFragmentShader::GLFragmentShader(const QString& fileName) : GLShader(fileName, GL_FRAGMENT_SHADER_ARB)
{
}
GLProgram::GLProgram() : m_linked(false), m_linkError(false), m_failed(false)
{
GLSHADERS_ASSERT_OPENGL("GLProgram::GLProgram", glCreateProgramObjectARB, return)
m_program = glCreateProgramObjectARB();
}
GLProgram::~GLProgram()
{
GLSHADERS_ASSERT_OPENGL("GLProgram::~GLProgram", glDeleteObjectARB, return)
glDeleteObjectARB(m_program);
}
void GLProgram::attach(const GLShader &shader)
{
GLSHADERS_ASSERT_OPENGL("GLProgram::attach", glAttachObjectARB, return)
glAttachObjectARB(m_program, shader.m_shader);
m_linked = m_linkError = false;
}
void GLProgram::detach(const GLShader &shader)
{
GLSHADERS_ASSERT_OPENGL("GLProgram::detach", glDetachObjectARB, return)
glDetachObjectARB(m_program, shader.m_shader);
m_linked = m_linkError = false;
}
bool GLProgram::failed()
{
if (m_failed || m_linkError)
return true;
if (m_linked)
return false;
GLSHADERS_ASSERT_OPENGL("GLProgram::failed", glLinkProgramARB && glGetObjectParameterivARB, return true)
glLinkProgramARB(m_program);
int status;
glGetObjectParameterivARB(m_program, GL_OBJECT_LINK_STATUS_ARB, &status);
m_linkError = !(m_linked = (status == 1));
return m_linkError;
}
QString GLProgram::log()
{
GLSHADERS_ASSERT_OPENGL("GLProgram::log", glGetObjectParameterivARB && glGetInfoLogARB,
return QLatin1String("Failed."))
int length;
glGetObjectParameterivARB(m_program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
char *log = new char[length + 1];
GLsizei glLength = length;
glGetInfoLogARB(m_program, glLength, &glLength, reinterpret_cast<GLcharARB*>(log));
log[glLength] = '\0';
QString result(log);
delete log;
return result;
}
void GLProgram::bind()
{
GLSHADERS_ASSERT_OPENGL("GLProgram::bind", glUseProgramObjectARB, return)
if (!failed())
glUseProgramObjectARB(m_program);
}
void GLProgram::unbind()
{
GLSHADERS_ASSERT_OPENGL("GLProgram::bind", glUseProgramObjectARB, return)
glUseProgramObjectARB(0);
}
bool GLProgram::hasParameter(const QString& name)
{
GLSHADERS_ASSERT_OPENGL("GLProgram::hasParameter", glGetUniformLocationARB, return false)
if (!failed()) {
QByteArray asciiName = name.toAscii();
return -1 != glGetUniformLocationARB(m_program, reinterpret_cast<const GLcharARB*>(asciiName.data()));
}
return false;
}
void GLProgram::setInt(const QString& name, int value)
{
GLSHADERS_ASSERT_OPENGL("GLProgram::setInt", glGetUniformLocationARB && glUniform1iARB, return)
if (!failed()) {
QByteArray asciiName = name.toAscii();
int loc = glGetUniformLocationARB(m_program, reinterpret_cast<const GLcharARB*>(asciiName.data()));
glUniform1iARB(loc, value);
}
}
void GLProgram::setFloat(const QString& name, float value)
{
GLSHADERS_ASSERT_OPENGL("GLProgram::setFloat", glGetUniformLocationARB && glUniform1fARB, return)
if (!failed()) {
QByteArray asciiName = name.toAscii();
int loc = glGetUniformLocationARB(m_program, reinterpret_cast<const GLcharARB*>(asciiName.data()));
glUniform1fARB(loc, value);
}
}
void GLProgram::setColor(const QString& name, QRgb value)
{
GLSHADERS_ASSERT_OPENGL("GLProgram::setColor", glGetUniformLocationARB && glUniform4fARB, return)
if (!failed()) {
QByteArray asciiName = name.toAscii();
int loc = glGetUniformLocationARB(m_program, reinterpret_cast<const GLcharARB*>(asciiName.data()));
QColor color(value);
glUniform4fARB(loc, color.redF(), color.greenF(), color.blueF(), color.alphaF());
}
}
void GLProgram::setMatrix(const QString& name, const gfx::Matrix4x4f &mat)
{
GLSHADERS_ASSERT_OPENGL("GLProgram::setMatrix", glGetUniformLocationARB && glUniformMatrix4fvARB, return)
if (!failed()) {
QByteArray asciiName = name.toAscii();
int loc = glGetUniformLocationARB(m_program, reinterpret_cast<const GLcharARB*>(asciiName.data()));
glUniformMatrix4fvARB(loc, 1, GL_FALSE, mat.bits());
}
}