Added wrapper classes for shaders/shader programs to ease the process of

compiling, linking, assigning uniforms, etc.  They're modeled after the ones
included in QtOpenGL, which we can't use at the moment because they require
a Qt OpenGL context.
This commit is contained in:
Andrzej Kapolka 2013-05-07 17:40:55 -07:00
parent a1c3e8515d
commit 7c8a06ed4d
9 changed files with 323 additions and 79 deletions

View file

@ -32,7 +32,7 @@ configure_file(InterfaceConfig.h.in ${PROJECT_BINARY_DIR}/includes/InterfaceConf
# grab the implementation and header files from src dirs
file(GLOB INTERFACE_SRCS src/*.cpp src/*.h)
foreach(SUBDIR ui)
foreach(SUBDIR ui renderer)
file(GLOB SUBDIR_SRCS src/${SUBDIR}/*.cpp src/${SUBDIR}/*.h)
set(INTERFACE_SRCS ${INTERFACE_SRCS} ${SUBDIR_SRCS})
endforeach(SUBDIR)

View file

@ -5,48 +5,31 @@
// Created by Andrzej Kapolka on 5/6/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include <QFile>
#include <QtDebug>
#include "Camera.h"
#include "Environment.h"
#include "renderer/ProgramObject.h"
#include "renderer/ShaderObject.h"
#include "world.h"
static GLhandleARB compileShader(int type, const QString& filename) {
QFile file(filename);
if (!file.open(QIODevice::ReadOnly)) {
qWarning() << "Couldn't find file." << filename;
return 0;
}
GLhandleARB shaderID = glCreateShaderObjectARB(type);
QByteArray source = file.readAll();
const char* sdata = source.constData();
glShaderSource(shaderID, 1, &sdata, 0);
glCompileShaderARB(shaderID);
return shaderID;
}
void Environment::init() {
_skyFromAtmosphereProgramID = glCreateProgramObjectARB();
glAttachObjectARB(_skyFromAtmosphereProgramID, compileShader(
GL_VERTEX_SHADER_ARB, "resources/shaders/SkyFromAtmosphere.vert"));
glAttachObjectARB(_skyFromAtmosphereProgramID, compileShader(
GL_FRAGMENT_SHADER_ARB, "resources/shaders/SkyFromAtmosphere.frag"));
glLinkProgramARB(_skyFromAtmosphereProgramID);
_cameraPosLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "v3CameraPos");
_lightPosLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "v3LightPos");
_invWavelengthLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "v3InvWavelength");
_innerRadiusLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "fInnerRadius");
_krESunLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "fKrESun");
_kmESunLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "fKmESun");
_kr4PiLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "fKr4PI");
_km4PiLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "fKm4PI");
_scaleLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "fScale");
_scaleDepthLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "fScaleDepth");
_scaleOverScaleDepthLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "fScaleOverScaleDepth");
_gLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "g");
_g2Location = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "g2");
_skyFromAtmosphereProgram = new ProgramObject();
_skyFromAtmosphereProgram->attachFromSourceFile(GL_VERTEX_SHADER_ARB, "resources/shaders/SkyFromAtmosphere.vert");
_skyFromAtmosphereProgram->attachFromSourceFile(GL_FRAGMENT_SHADER_ARB, "resources/shaders/SkyFromAtmosphere.frag");
_skyFromAtmosphereProgram->link();
_cameraPosLocation = _skyFromAtmosphereProgram->getUniformLocation("v3CameraPos");
_lightPosLocation = _skyFromAtmosphereProgram->getUniformLocation("v3LightPos");
_invWavelengthLocation = _skyFromAtmosphereProgram->getUniformLocation("v3InvWavelength");
_innerRadiusLocation = _skyFromAtmosphereProgram->getUniformLocation("fInnerRadius");
_krESunLocation = _skyFromAtmosphereProgram->getUniformLocation("fKrESun");
_kmESunLocation = _skyFromAtmosphereProgram->getUniformLocation("fKmESun");
_kr4PiLocation = _skyFromAtmosphereProgram->getUniformLocation("fKr4PI");
_km4PiLocation = _skyFromAtmosphereProgram->getUniformLocation("fKm4PI");
_scaleLocation = _skyFromAtmosphereProgram->getUniformLocation("fScale");
_scaleDepthLocation = _skyFromAtmosphereProgram->getUniformLocation("fScaleDepth");
_scaleOverScaleDepthLocation = _skyFromAtmosphereProgram->getUniformLocation("fScaleOverScaleDepth");
_gLocation = _skyFromAtmosphereProgram->getUniformLocation("g");
_g2Location = _skyFromAtmosphereProgram->getUniformLocation("g2");
}
void Environment::render(Camera& camera) {
@ -68,25 +51,25 @@ void Environment::render(Camera& camera) {
// the constants here are from Sean O'Neil's GPU Gems entry
// (http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html), GameEngine.cpp
glUseProgramObjectARB(_skyFromAtmosphereProgramID);
glUniform3fARB(_cameraPosLocation, relativeCameraPos.x, relativeCameraPos.y, relativeCameraPos.z);
_skyFromAtmosphereProgram->bind();
_skyFromAtmosphereProgram->setUniform(_cameraPosLocation, relativeCameraPos);
glm::vec3 lightDirection = glm::normalize(getSunLocation());
glUniform3fARB(_lightPosLocation, lightDirection.x, lightDirection.y, lightDirection.z);
glUniform3fARB(_invWavelengthLocation,
_skyFromAtmosphereProgram->setUniform(_lightPosLocation, lightDirection);
_skyFromAtmosphereProgram->setUniform(_invWavelengthLocation,
1 / powf(getScatteringWavelengths().r, 4.0f),
1 / powf(getScatteringWavelengths().g, 4.0f),
1 / powf(getScatteringWavelengths().b, 4.0f));
glUniform1fARB(_innerRadiusLocation, getAtmosphereInnerRadius());
glUniform1fARB(_krESunLocation, getRayleighScattering() * getSunBrightness());
glUniform1fARB(_kmESunLocation, getMieScattering() * getSunBrightness());
glUniform1fARB(_kr4PiLocation, getRayleighScattering() * 4.0f * PIf);
glUniform1fARB(_km4PiLocation, getMieScattering() * 4.0f * PIf);
glUniform1fARB(_scaleLocation, 1.0f / (getAtmosphereOuterRadius() - getAtmosphereInnerRadius()));
glUniform1fARB(_scaleDepthLocation, 0.25f);
glUniform1fARB(_scaleOverScaleDepthLocation,
_skyFromAtmosphereProgram->setUniform(_innerRadiusLocation, getAtmosphereInnerRadius());
_skyFromAtmosphereProgram->setUniform(_krESunLocation, getRayleighScattering() * getSunBrightness());
_skyFromAtmosphereProgram->setUniform(_kmESunLocation, getMieScattering() * getSunBrightness());
_skyFromAtmosphereProgram->setUniform(_kr4PiLocation, getRayleighScattering() * 4.0f * PIf);
_skyFromAtmosphereProgram->setUniform(_km4PiLocation, getMieScattering() * 4.0f * PIf);
_skyFromAtmosphereProgram->setUniform(_scaleLocation, 1.0f / (getAtmosphereOuterRadius() - getAtmosphereInnerRadius()));
_skyFromAtmosphereProgram->setUniform(_scaleDepthLocation, 0.25f);
_skyFromAtmosphereProgram->setUniform(_scaleOverScaleDepthLocation,
(1.0f / (getAtmosphereOuterRadius() - getAtmosphereInnerRadius())) / 0.25f);
glUniform1fARB(_gLocation, -0.990f);
glUniform1fARB(_g2Location, -0.990f * -0.990f);
_skyFromAtmosphereProgram->setUniform(_gLocation, -0.990f);
_skyFromAtmosphereProgram->setUniform(_g2Location, -0.990f * -0.990f);
glFrontFace(GL_CW);
glDepthMask(GL_FALSE);
@ -95,7 +78,7 @@ void Environment::render(Camera& camera) {
glDepthMask(GL_TRUE);
glFrontFace(GL_CCW);
glUseProgramObjectARB(0);
_skyFromAtmosphereProgram->release();
glPopMatrix();

View file

@ -2,7 +2,7 @@
// Environment.h
// interface
//
// Created by Andrzej Kapolka on 5/16/13.
// Created by Andrzej Kapolka on 5/6/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
@ -13,6 +13,7 @@
#include "InterfaceConfig.h"
class Camera;
class ProgramObject;
class Environment : public EnvironmentData {
public:
@ -22,7 +23,7 @@ public:
private:
GLhandleARB _skyFromAtmosphereProgramID;
ProgramObject* _skyFromAtmosphereProgram;
int _cameraPosLocation;
int _lightPosLocation;
int _invWavelengthLocation;

View file

@ -58,6 +58,8 @@
#include "ui/MenuColumn.h"
#include "ui/Menu.h"
#include "ui/TextRenderer.h"
#include "renderer/ProgramObject.h"
#include "renderer/ShaderObject.h"
#include "Camera.h"
#include "Avatar.h"
@ -178,7 +180,7 @@ bool chatEntryOn = false; // Whether to show the chat entry
bool oculusOn = false; // Whether to configure the display for the Oculus Rift
GLuint oculusTextureID = 0; // The texture to which we render for Oculus distortion
GLhandleARB oculusProgramID = 0; // The GLSL program containing the distortion shader
ProgramObject* oculusProgram = 0; // The GLSL program containing the distortion shader
float oculusDistortionScale = 1.25; // Controls the Oculus field of view
//
@ -813,18 +815,16 @@ void displayOculus(Camera& whichCamera) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
GLhandleARB shaderID = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
glShaderSourceARB(shaderID, 1, &DISTORTION_FRAGMENT_SHADER, 0);
glCompileShaderARB(shaderID);
::oculusProgramID = glCreateProgramObjectARB();
glAttachObjectARB(::oculusProgramID, shaderID);
glLinkProgramARB(::oculusProgramID);
textureLocation = glGetUniformLocationARB(::oculusProgramID, "texture");
lensCenterLocation = glGetUniformLocationARB(::oculusProgramID, "lensCenter");
screenCenterLocation = glGetUniformLocationARB(::oculusProgramID, "screenCenter");
scaleLocation = glGetUniformLocationARB(::oculusProgramID, "scale");
scaleInLocation = glGetUniformLocationARB(::oculusProgramID, "scaleIn");
hmdWarpParamLocation = glGetUniformLocationARB(::oculusProgramID, "hmdWarpParam");
::oculusProgram = new ProgramObject();
::oculusProgram->attachFromSourceCode(GL_FRAGMENT_SHADER_ARB, DISTORTION_FRAGMENT_SHADER);
::oculusProgram->link();
textureLocation = ::oculusProgram->getUniformLocation("texture");
lensCenterLocation = ::oculusProgram->getUniformLocation("lensCenter");
screenCenterLocation = ::oculusProgram->getUniformLocation("screenCenter");
scaleLocation = ::oculusProgram->getUniformLocation("scale");
scaleInLocation = ::oculusProgram->getUniformLocation("scaleIn");
hmdWarpParamLocation = ::oculusProgram->getUniformLocation("hmdWarpParam");
} else {
glBindTexture(GL_TEXTURE_2D, ::oculusTextureID);
@ -844,13 +844,13 @@ void displayOculus(Camera& whichCamera) {
glDisable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glUseProgramObjectARB(::oculusProgramID);
glUniform1iARB(textureLocation, 0);
glUniform2fARB(lensCenterLocation, 0.287994, 0.5); // see SDK docs, p. 29
glUniform2fARB(screenCenterLocation, 0.25, 0.5);
glUniform2fARB(scaleLocation, 0.25 * scaleFactor, 0.5 * scaleFactor * aspectRatio);
glUniform2fARB(scaleInLocation, 4, 2 / aspectRatio);
glUniform4fARB(hmdWarpParamLocation, 1.0, 0.22, 0.24, 0);
::oculusProgram->bind();
::oculusProgram->setUniform(textureLocation, 0);
::oculusProgram->setUniform(lensCenterLocation, 0.287994, 0.5); // see SDK docs, p. 29
::oculusProgram->setUniform(screenCenterLocation, 0.25, 0.5);
::oculusProgram->setUniform(scaleLocation, 0.25 * scaleFactor, 0.5 * scaleFactor * aspectRatio);
::oculusProgram->setUniform(scaleInLocation, 4, 2 / aspectRatio);
::oculusProgram->setUniform(hmdWarpParamLocation, 1.0, 0.22, 0.24, 0);
glColor3f(1, 0, 1);
glBegin(GL_QUADS);
@ -864,8 +864,8 @@ void displayOculus(Camera& whichCamera) {
glVertex2f(0, HEIGHT);
glEnd();
glUniform2fARB(lensCenterLocation, 0.787994, 0.5);
glUniform2fARB(screenCenterLocation, 0.75, 0.5);
::oculusProgram->setUniform(lensCenterLocation, 0.787994, 0.5);
::oculusProgram->setUniform(screenCenterLocation, 0.75, 0.5);
glBegin(GL_QUADS);
glTexCoord2f(0.5, 0);
@ -881,7 +881,7 @@ void displayOculus(Camera& whichCamera) {
glEnable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgramObjectARB(0);
::oculusProgram->release();
glPopMatrix();
}

View file

@ -0,0 +1,119 @@
//
// ProgramObject.cpp
// interface
//
// Created by Andrzej Kapolka on 5/7/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include "ProgramObject.h"
#include "ShaderObject.h"
ProgramObject::ProgramObject() : _handle(glCreateProgramObjectARB()) {
}
ProgramObject::~ProgramObject() {
glDeleteObjectARB(_handle);
}
void ProgramObject::attach(ShaderObject* shader) {
glAttachObjectARB(_handle, shader->getHandle());
}
bool ProgramObject::attachFromSourceCode(int type, const char* source) {
ShaderObject* shader = new ShaderObject(type);
if (shader->compileSourceCode(source)) {
attach(shader);
return true;
} else {
delete shader;
return false;
}
}
bool ProgramObject::attachFromSourceFile(int type, const char* filename) {
ShaderObject* shader = new ShaderObject(type);
if (shader->compileSourceFile(filename)) {
attach(shader);
return true;
} else {
delete shader;
return false;
}
}
bool ProgramObject::link() {
glLinkProgramARB(_handle);
int status;
glGetObjectParameterivARB(_handle, GL_OBJECT_LINK_STATUS_ARB, &status);
return status;
}
QByteArray ProgramObject::getLog() const {
int length;
glGetObjectParameterivARB(_handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
QByteArray log(length, 0);
glGetInfoLogARB(_handle, length, 0, log.data());
return log;
}
void ProgramObject::bind() const {
glUseProgramObjectARB(_handle);
}
void ProgramObject::release() const {
glUseProgramObjectARB(0);
}
int ProgramObject::getUniformLocation(const char* name) const {
return glGetUniformLocationARB(_handle, name);
}
void ProgramObject::setUniform(int location, int value) {
glUniform1iARB(location, value);
}
void ProgramObject::setUniform(const char* name, int value) {
setUniform(getUniformLocation(name), value);
}
void ProgramObject::setUniform(int location, float value) {
glUniform1fARB(location, value);
}
void ProgramObject::setUniform(const char* name, float value) {
setUniform(getUniformLocation(name), value);
}
void ProgramObject::setUniform(int location, float x, float y) {
glUniform2fARB(location, x, y);
}
void ProgramObject::setUniform(const char* name, float x, float y) {
setUniform(getUniformLocation(name), x, y);
}
void ProgramObject::setUniform(int location, const glm::vec3& value) {
glUniform3fARB(location, value.x, value.y, value.z);
}
void ProgramObject::setUniform(const char* name, const glm::vec3& value) {
setUniform(getUniformLocation(name), value);
}
void ProgramObject::setUniform(int location, float x, float y, float z) {
glUniform3fARB(location, x, y, z);
}
void ProgramObject::setUniform(const char* name, float x, float y, float z) {
setUniform(getUniformLocation(name), x, y, z);
}
void ProgramObject::setUniform(int location, float x, float y, float z, float w) {
glUniform4fARB(location, x, y, z, w);
}
void ProgramObject::setUniform(const char* name, float x, float y, float z, float w) {
setUniform(getUniformLocation(name), x, y, z, w);
}

View file

@ -0,0 +1,66 @@
//
// ProgramObject.h
// interface
//
// Created by Andrzej Kapolka on 5/7/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__ProgramObject__
#define __interface__ProgramObject__
#include <QObject>
#include <glm/glm.hpp>
#include "InterfaceConfig.h"
class ShaderObject;
class ProgramObject {
public:
ProgramObject();
~ProgramObject();
GLhandleARB getHandle() const { return _handle; }
void attach(ShaderObject* shader);
bool attachFromSourceCode(int type, const char* source);
bool attachFromSourceFile(int type, const char* filename);
bool link();
QByteArray getLog() const;
void bind() const;
void release() const;
int getUniformLocation(const char* name) const;
void setUniform(int location, int value);
void setUniform(const char* name, int value);
void setUniform(int location, float value);
void setUniform(const char* name, float value);
void setUniform(int location, float x, float y);
void setUniform(const char* name, float x, float y);
void setUniform(int location, const glm::vec3& value);
void setUniform(const char* name, const glm::vec3& value);
void setUniform(int location, float x, float y, float z);
void setUniform(const char* name, float x, float y, float z);
void setUniform(int location, float x, float y, float z, float w);
void setUniform(const char* name, float x, float y, float z, float w);
private:
Q_DISABLE_COPY(ProgramObject)
GLhandleARB _handle;
};
#endif /* defined(__interface__ProgramObject__) */

View file

@ -0,0 +1,39 @@
//
// ShaderObject.cpp
// interface
//
// Created by Andrzej Kapolka on 5/7/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include <QFile>
#include "ShaderObject.h"
ShaderObject::ShaderObject(int type)
: _handle(glCreateShaderObjectARB(type)) {
}
ShaderObject::~ShaderObject() {
glDeleteObjectARB(_handle);
}
bool ShaderObject::compileSourceCode(const char* data) {
glShaderSource(_handle, 1, &data, 0);
glCompileShaderARB(_handle);
int status;
glGetObjectParameterivARB(_handle, GL_OBJECT_COMPILE_STATUS_ARB, &status);
return status;
}
bool ShaderObject::compileSourceFile(const char* filename) {
QFile file(filename);
return file.open(QIODevice::ReadOnly) && compileSourceCode(file.readAll().constData());
}
QByteArray ShaderObject::getLog() const {
int length;
glGetObjectParameterivARB(_handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
QByteArray log(length, 0);
glGetInfoLogARB(_handle, length, 0, log.data());
return log;
}

View file

@ -0,0 +1,36 @@
//
// ShaderObject.h
// interface
//
// Created by Andrzej Kapolka on 5/7/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__ShaderObject__
#define __interface__ShaderObject__
#include <QObject>
#include "InterfaceConfig.h"
class ShaderObject {
public:
ShaderObject(int type);
~ShaderObject();
GLhandleARB getHandle() const { return _handle; }
bool compileSourceCode(const char* data);
bool compileSourceFile(const char* filename);
QByteArray getLog() const;
private:
Q_DISABLE_COPY(ShaderObject)
GLhandleARB _handle;
};
#endif /* defined(__interface__ShaderObject__) */

View file

@ -2,7 +2,7 @@
// EnvironmentData.h
// interface
//
// Created by Andrzej Kapolka on 5/16/13.
// Created by Andrzej Kapolka on 5/6/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//