Use multi-pass rendering with seperate ambient and light shaders

This commit is contained in:
Matthias Schiffer 2009-12-18 13:31:07 +01:00
parent b3b74dc2af
commit 4e3efa239c
10 changed files with 148 additions and 48 deletions

8
shader/ambient.frag Normal file
View file

@ -0,0 +1,8 @@
uniform sampler2D tex;
varying vec4 ambient;
void main() {
gl_FragColor = ambient * texture2D(tex, gl_TexCoord[0].st);
}

8
shader/ambient.vert Normal file
View file

@ -0,0 +1,8 @@
varying vec4 ambient;
void main() {
ambient = gl_LightModel.ambient * gl_FrontMaterial.ambient;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}

View file

@ -1,6 +1,6 @@
uniform sampler2D tex; uniform sampler2D tex;
varying vec4 diffuse, ambientGlobal, ambient; varying vec4 diffuse, ambient;
varying vec3 normal, pos; varying vec3 normal, pos;
@ -10,8 +10,6 @@ void main() {
vec4 color, specularColor; vec4 color, specularColor;
float dist, att, specularFactor; float dist, att, specularFactor;
color = ambientGlobal;
n = normalize(normal); n = normalize(normal);
l = gl_LightSource[0].position.xyz - pos; l = gl_LightSource[0].position.xyz - pos;
@ -26,7 +24,7 @@ void main() {
att = 1.0 / (gl_LightSource[0].constantAttenuation + att = 1.0 / (gl_LightSource[0].constantAttenuation +
gl_LightSource[0].linearAttenuation * dist + gl_LightSource[0].linearAttenuation * dist +
gl_LightSource[0].quadraticAttenuation * dist * dist); gl_LightSource[0].quadraticAttenuation * dist * dist);
color += att * (diffuse * NdotL + ambient); color = att * (diffuse * NdotL + ambient);
refl = normalize(reflect(-l, n)); refl = normalize(reflect(-l, n));
eye = normalize(-pos); eye = normalize(-pos);
@ -34,10 +32,10 @@ void main() {
RdotE = max(dot(refl, eye), 0.0); RdotE = max(dot(refl, eye), 0.0);
specularFactor = att * pow(RdotE, gl_FrontMaterial.shininess); specularFactor = att * pow(RdotE, gl_FrontMaterial.shininess);
specularColor = specularFactor * gl_FrontMaterial.specular * gl_LightSource[0].specular; specularColor = specularFactor * gl_FrontMaterial.specular * gl_LightSource[0].specular;
gl_FragColor = color * texture2D(tex, gl_TexCoord[0].st) + specularColor;
} }
else { else {
specularColor = vec4(0, 0, 0, 1); gl_FragColor = vec4(0, 0, 0, 1);
} }
gl_FragColor = color * texture2D(tex, gl_TexCoord[0].st) + specularColor;
} }

View file

@ -1,4 +1,4 @@
varying vec4 diffuse, ambientGlobal, ambient; varying vec4 diffuse, ambient;
varying vec3 normal, pos; varying vec3 normal, pos;
@ -10,7 +10,6 @@ void main() {
diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse; diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;
ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient; ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
ambientGlobal = gl_LightModel.ambient * gl_FrontMaterial.ambient;
gl_TexCoord[0] = gl_MultiTexCoord0; gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform(); gl_Position = ftransform();

View file

@ -34,9 +34,9 @@ Game::Game(bool multisample) : playerPos(vmml::vec3f::ZERO), playerRotY(vmml::ma
glClearColor(0.0, 0.0, 0.0, 1.0); glClearColor(0.0, 0.0, 0.0, 1.0);
glClearDepth(1.0); glClearDepth(1.0);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL); //glDepthFunc(GL_LEQUAL);
//glEnable(GL_BLEND); glEnable(GL_BLEND);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#ifndef _WIN32 #ifndef _WIN32
@ -50,7 +50,7 @@ Game::Game(bool multisample) : playerPos(vmml::vec3f::ZERO), playerRotY(vmml::ma
glLightfv(GL_LIGHT0, GL_SPECULAR, vmml::vec4f::ONE.array); glLightfv(GL_LIGHT0, GL_SPECULAR, vmml::vec4f::ONE.array);
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0); glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0);
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.2); glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.2);
glEnable(GL_LIGHT0); glDisable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL); glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
@ -61,8 +61,6 @@ Game::Game(bool multisample) : playerPos(vmml::vec3f::ZERO), playerRotY(vmml::ma
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW); glFrontFace(GL_CCW);
Shader::loadProgram("default.vert", "default.frag");
loadLevel("level.xml"); loadLevel("level.xml");
triangles.insert(triangles.end(), level->getRooms().front().walls.begin(), level->getRooms().front().walls.end()); triangles.insert(triangles.end(), level->getRooms().front().walls.begin(), level->getRooms().front().walls.end());
std::sort(triangles.begin(), triangles.end(), Renderer::TextureSorter()); std::sort(triangles.begin(), triangles.end(), Renderer::TextureSorter());

View file

@ -18,9 +18,15 @@
*/ */
#include "Renderer.h" #include "Renderer.h"
#include "Shader.h"
namespace Zoom { namespace Zoom {
Renderer::Renderer() : activeTexture(0), renderVisitor(this) {
ambientShader = boost::shared_ptr<Shader>(Shader::load("ambient.vert", "ambient.frag"));
lightShader = boost::shared_ptr<Shader>(Shader::load("light.vert", "light.frag"));
}
void Renderer::render(const BSPTree &tree) { void Renderer::render(const BSPTree &tree) {
vmml::mat4f transform, inverseTransform; vmml::mat4f transform, inverseTransform;
glGetFloatv(GL_MODELVIEW_MATRIX, transform.array); glGetFloatv(GL_MODELVIEW_MATRIX, transform.array);

View file

@ -20,19 +20,25 @@
#ifndef ZOOM_RENDERER_H_ #ifndef ZOOM_RENDERER_H_
#define ZOOM_RENDERER_H_ #define ZOOM_RENDERER_H_
#include "BSPTree.h"
#include "gl.h" #include "gl.h"
#include "BSPTree.h"
#include "Shader.h"
namespace Zoom { namespace Zoom {
class Renderer { class Renderer {
public: public:
Renderer() : activeTexture(0), renderVisitor(this) {} Renderer();
void render(const BSPTree &tree); void render(const BSPTree &tree);
template <typename T> template <typename T>
void render(const T &triangles) { void render(const T &triangles) {
Shader::enable(ambientShader);
glBlendFunc(GL_ONE, GL_ZERO);
glDepthFunc(GL_LEQUAL);
typename T::const_iterator t = triangles.begin(); typename T::const_iterator t = triangles.begin();
if(t == triangles.end()) if(t == triangles.end())
return; return;
@ -44,6 +50,20 @@ class Renderer {
renderTriangle(t->triangle); renderTriangle(t->triangle);
} }
glEnd(); glEnd();
Shader::enable(lightShader);
glBlendFunc(GL_ONE, GL_ONE);
glDepthFunc(GL_EQUAL);
t = triangles.begin();
useTexture(t->triangle.getTexture());
glBegin(GL_TRIANGLES);
for(; t != triangles.end(); ++t) {
renderTriangle(t->triangle);
}
glEnd();
} }
struct TextureSorter { struct TextureSorter {
@ -68,6 +88,7 @@ class Renderer {
Renderer *renderer; Renderer *renderer;
}; };
boost::shared_ptr<Shader> ambientShader, lightShader;
unsigned activeTexture; unsigned activeTexture;
const RenderVisitor renderVisitor; const RenderVisitor renderVisitor;

View file

@ -18,6 +18,7 @@
*/ */
#include "Shader.h" #include "Shader.h"
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <vector> #include <vector>
@ -25,8 +26,9 @@
namespace Zoom { namespace Zoom {
bool Shader::loadProgram(const std::string &vertexShader, const std::string &fragmentShader) { boost::shared_ptr<Shader> Shader::load(const std::string &vertexShader, const std::string &fragmentShader) {
GLhandleARB program, vs = 0, fs = 0; GLhandleARB program, vs = 0, fs = 0;
bool ok = false;
if(!vertexShader.empty()) if(!vertexShader.empty())
vs = loadShader(vertexShader, GL_VERTEX_SHADER_ARB); vs = loadShader(vertexShader, GL_VERTEX_SHADER_ARB);
@ -36,25 +38,41 @@ bool Shader::loadProgram(const std::string &vertexShader, const std::string &fra
program = glCreateProgramObjectARB(); program = glCreateProgramObjectARB();
if(vs) if(program) {
glAttachObjectARB(program, vs); if(vs)
glAttachObjectARB(program, vs);
if(fs) if(fs)
glAttachObjectARB(program, fs); glAttachObjectARB(program, fs);
glLinkProgramARB(program); glLinkProgramARB(program);
printInfoLog(program); if(glGetError()) {
printInfoLog(program);
}
else {
ok = true;
}
glUseProgramObjectARB(program); if(vs) {
glDeleteObjectARB(vs);
}
return true; if(fs) {
glDeleteObjectARB(fs);
}
}
if(ok)
return boost::shared_ptr<Shader>(new Shader(program));
else
return boost::shared_ptr<Shader>();
} }
GLhandleARB Shader::loadShader(const std::string &name, GLenum type) { GLhandleARB Shader::loadShader(const std::string &name, GLenum type) {
std::vector<std::string> lines; std::vector<std::string> lines;
std::ifstream file(("shader/" + name).c_str(), std::ios_base::in); std::ifstream file(("shader/" + name).c_str(), std::ios_base::in);
if(!file.good()) if(!file.good())
throw std::ios::failure("Can't read file '" + name + "'"); return 0;
while(file.good() && !file.eof()) { while(file.good() && !file.eof()) {
std::string line; std::string line;
@ -69,12 +87,26 @@ GLhandleARB Shader::loadShader(const std::string &name, GLenum type) {
strings[i] = lines[i].c_str(); strings[i] = lines[i].c_str();
} }
bool ok = false;
GLhandleARB shader = glCreateShaderObjectARB(type); GLhandleARB shader = glCreateShaderObjectARB(type);
glShaderSourceARB(shader, lines.size(), strings.get(), 0);
glCompileShaderARB(shader);
printInfoLog(shader);
return shader; if(shader) {
glShaderSourceARB(shader, lines.size(), strings.get(), 0);
glCompileShaderARB(shader);
if(glGetError()) {
printInfoLog(shader);
glDeleteObjectARB(shader);
}
else {
ok = true;
}
}
if(ok)
return shader;
else
return 0;
} }
void Shader::printInfoLog(GLhandleARB obj) { void Shader::printInfoLog(GLhandleARB obj) {

View file

@ -21,19 +21,42 @@
#define ZOOM_SHADER_H_ #define ZOOM_SHADER_H_
#include "gl.h" #include "gl.h"
#include <string> #include <string>
#include <boost/shared_ptr.hpp>
namespace Zoom { namespace Zoom {
class Shader { class Shader {
public: public:
static bool loadProgram(const std::string &vertexShader, const std::string &fragmentShader); static boost::shared_ptr<Shader> load(const std::string &vertexShader, const std::string &fragmentShader);
static void enable(boost::shared_ptr<Shader> shader) {
if(shader)
glUseProgramObjectARB(shader->handle);
else
glUseProgramObjectARB(0);
}
static void disable() {
enable(boost::shared_ptr<Shader>());
}
~Shader() {
glDeleteObjectARB(handle);
}
private: private:
Shader();
static GLhandleARB loadShader(const std::string &name, GLenum type); static GLhandleARB loadShader(const std::string &name, GLenum type);
static void printInfoLog(GLhandleARB obj); static void printInfoLog(GLhandleARB obj);
Shader(GLhandleARB handle0) : handle(handle0) {}
// Prevent shallow copy
Shader(const Shader &o);
Shader& operator=(const Shader &o);
GLhandleARB handle;
}; };
} }

View file

@ -22,6 +22,8 @@
#include "config.h" #include "config.h"
#include "gl.h" #include "gl.h"
#include <cstdio>
#ifdef _WIN32 #ifdef _WIN32
#else #else
@ -69,7 +71,7 @@ bool WGLInit(HINSTANCE hInstance, HWND *hWnd, HDC *hDC, HGLRC *hRC) {
if (!RegisterClass(&wc)) { if (!RegisterClass(&wc)) {
MessageBox(0, "Failed To Register The Window Class.", "ERROR", MB_OK|MB_ICONEXCLAMATION); MessageBox(0, "Failed To Register The Window Class.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
return false; // Exit And Return FALSE return false;
} }
DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
@ -421,24 +423,29 @@ int main() {
case GenericEvent: case GenericEvent:
if(event.xcookie.extension == xi_opcode && XGetEventData(disp, &event.xcookie)) { if(event.xcookie.extension == xi_opcode && XGetEventData(disp, &event.xcookie)) {
XIRawEvent *rawEvent = reinterpret_cast<XIRawEvent*>(event.xcookie.data); switch(event.xcookie.evtype) {
case XI_RawMotion:
XIRawEvent *rawEvent = reinterpret_cast<XIRawEvent*>(event.xcookie.data);
float deltaX = 0, deltaY = 0; float deltaX = 0, deltaY = 0;
double *rawValuator = rawEvent->raw_values; double *rawValuator = rawEvent->raw_values;
if(XIMaskIsSet(rawEvent->valuators.mask, 0)) { if(rawEvent->valuators.mask_len >= 1) {
deltaX = (float)*rawValuator; if(XIMaskIsSet(rawEvent->valuators.mask, 0)) {
++rawValuator; deltaX = (float)*rawValuator;
++rawValuator;
}
if(XIMaskIsSet(rawEvent->valuators.mask, 1)) {
deltaY = (float)*rawValuator;
++rawValuator;
}
}
if(deltaX != 0 || deltaY != 0)
game.turn(deltaX, deltaY);
} }
if(XIMaskIsSet(rawEvent->valuators.mask, 1)) {
deltaY = (float)*rawValuator;
++rawValuator;
}
if(deltaX != 0 || deltaY != 0)
game.turn(deltaX, deltaY);
XFreeEventData(disp, &event.xcookie); XFreeEventData(disp, &event.xcookie);
} }
} }