From 4e3efa239c9bcb5dd26b4ad9a4d43d4d6a266e6f Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 18 Dec 2009 13:31:07 +0100 Subject: Use multi-pass rendering with seperate ambient and light shaders --- shader/ambient.frag | 8 +++++++ shader/ambient.vert | 8 +++++++ shader/default.frag | 43 -------------------------------------- shader/default.vert | 17 --------------- shader/light.frag | 41 ++++++++++++++++++++++++++++++++++++ shader/light.vert | 16 ++++++++++++++ src/Game.cpp | 8 +++---- src/Renderer.cpp | 6 ++++++ src/Renderer.h | 25 ++++++++++++++++++++-- src/Shader.cpp | 60 ++++++++++++++++++++++++++++++++++++++++------------- src/Shader.h | 29 +++++++++++++++++++++++--- src/zoom.cpp | 41 +++++++++++++++++++++--------------- 12 files changed, 201 insertions(+), 101 deletions(-) create mode 100644 shader/ambient.frag create mode 100644 shader/ambient.vert delete mode 100644 shader/default.frag delete mode 100644 shader/default.vert create mode 100644 shader/light.frag create mode 100644 shader/light.vert diff --git a/shader/ambient.frag b/shader/ambient.frag new file mode 100644 index 0000000..cef0a3b --- /dev/null +++ b/shader/ambient.frag @@ -0,0 +1,8 @@ +uniform sampler2D tex; + +varying vec4 ambient; + + +void main() { + gl_FragColor = ambient * texture2D(tex, gl_TexCoord[0].st); +} diff --git a/shader/ambient.vert b/shader/ambient.vert new file mode 100644 index 0000000..41a36e7 --- /dev/null +++ b/shader/ambient.vert @@ -0,0 +1,8 @@ +varying vec4 ambient; + +void main() { + ambient = gl_LightModel.ambient * gl_FrontMaterial.ambient; + + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_Position = ftransform(); +} diff --git a/shader/default.frag b/shader/default.frag deleted file mode 100644 index e2acad0..0000000 --- a/shader/default.frag +++ /dev/null @@ -1,43 +0,0 @@ -uniform sampler2D tex; - -varying vec4 diffuse, ambientGlobal, ambient; -varying vec3 normal, pos; - - -void main() { - vec3 n, l, refl, eye; - float NdotL, RdotE; - vec4 color, specularColor; - float dist, att, specularFactor; - - color = ambientGlobal; - - n = normalize(normal); - - l = gl_LightSource[0].position.xyz - pos; - - dist = length(l); - l /= dist; - - /* compute the dot product between normal and normalized lightdir */ - NdotL = max(dot(n, l), 0.0); - - if (NdotL > 0.0) { - att = 1.0 / (gl_LightSource[0].constantAttenuation + - gl_LightSource[0].linearAttenuation * dist + - gl_LightSource[0].quadraticAttenuation * dist * dist); - color += att * (diffuse * NdotL + ambient); - - refl = normalize(reflect(-l, n)); - eye = normalize(-pos); - - RdotE = max(dot(refl, eye), 0.0); - specularFactor = att * pow(RdotE, gl_FrontMaterial.shininess); - specularColor = specularFactor * gl_FrontMaterial.specular * gl_LightSource[0].specular; - } - else { - specularColor = vec4(0, 0, 0, 1); - } - - gl_FragColor = color * texture2D(tex, gl_TexCoord[0].st) + specularColor; -} diff --git a/shader/default.vert b/shader/default.vert deleted file mode 100644 index 00b8118..0000000 --- a/shader/default.vert +++ /dev/null @@ -1,17 +0,0 @@ -varying vec4 diffuse, ambientGlobal, ambient; -varying vec3 normal, pos; - - -void main() { - normal = normalize(gl_NormalMatrix * gl_Normal); - - pos = vec3(gl_ModelViewMatrix * gl_Vertex); - - diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse; - - ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient; - ambientGlobal = gl_LightModel.ambient * gl_FrontMaterial.ambient; - - gl_TexCoord[0] = gl_MultiTexCoord0; - gl_Position = ftransform(); -} diff --git a/shader/light.frag b/shader/light.frag new file mode 100644 index 0000000..c3cdbfb --- /dev/null +++ b/shader/light.frag @@ -0,0 +1,41 @@ +uniform sampler2D tex; + +varying vec4 diffuse, ambient; +varying vec3 normal, pos; + + +void main() { + vec3 n, l, refl, eye; + float NdotL, RdotE; + vec4 color, specularColor; + float dist, att, specularFactor; + + n = normalize(normal); + + l = gl_LightSource[0].position.xyz - pos; + + dist = length(l); + l /= dist; + + /* compute the dot product between normal and normalized lightdir */ + NdotL = max(dot(n, l), 0.0); + + if (NdotL > 0.0) { + att = 1.0 / (gl_LightSource[0].constantAttenuation + + gl_LightSource[0].linearAttenuation * dist + + gl_LightSource[0].quadraticAttenuation * dist * dist); + color = att * (diffuse * NdotL + ambient); + + refl = normalize(reflect(-l, n)); + eye = normalize(-pos); + + RdotE = max(dot(refl, eye), 0.0); + specularFactor = att * pow(RdotE, gl_FrontMaterial.shininess); + specularColor = specularFactor * gl_FrontMaterial.specular * gl_LightSource[0].specular; + + gl_FragColor = color * texture2D(tex, gl_TexCoord[0].st) + specularColor; + } + else { + gl_FragColor = vec4(0, 0, 0, 1); + } +} diff --git a/shader/light.vert b/shader/light.vert new file mode 100644 index 0000000..b97da78 --- /dev/null +++ b/shader/light.vert @@ -0,0 +1,16 @@ +varying vec4 diffuse, ambient; +varying vec3 normal, pos; + + +void main() { + normal = normalize(gl_NormalMatrix * gl_Normal); + + pos = vec3(gl_ModelViewMatrix * gl_Vertex); + + diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse; + + ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient; + + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_Position = ftransform(); +} diff --git a/src/Game.cpp b/src/Game.cpp index 93b13c4..625d4d4 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -34,9 +34,9 @@ Game::Game(bool multisample) : playerPos(vmml::vec3f::ZERO), playerRotY(vmml::ma glClearColor(0.0, 0.0, 0.0, 1.0); glClearDepth(1.0); 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); #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); glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0); glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.2); - glEnable(GL_LIGHT0); + glDisable(GL_LIGHT0); glEnable(GL_COLOR_MATERIAL); 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); glFrontFace(GL_CCW); - Shader::loadProgram("default.vert", "default.frag"); - loadLevel("level.xml"); triangles.insert(triangles.end(), level->getRooms().front().walls.begin(), level->getRooms().front().walls.end()); std::sort(triangles.begin(), triangles.end(), Renderer::TextureSorter()); diff --git a/src/Renderer.cpp b/src/Renderer.cpp index ad4849b..8b3d689 100644 --- a/src/Renderer.cpp +++ b/src/Renderer.cpp @@ -18,9 +18,15 @@ */ #include "Renderer.h" +#include "Shader.h" namespace Zoom { +Renderer::Renderer() : activeTexture(0), renderVisitor(this) { + ambientShader = boost::shared_ptr(Shader::load("ambient.vert", "ambient.frag")); + lightShader = boost::shared_ptr(Shader::load("light.vert", "light.frag")); +} + void Renderer::render(const BSPTree &tree) { vmml::mat4f transform, inverseTransform; glGetFloatv(GL_MODELVIEW_MATRIX, transform.array); diff --git a/src/Renderer.h b/src/Renderer.h index fb98e38..ae9af4a 100644 --- a/src/Renderer.h +++ b/src/Renderer.h @@ -20,19 +20,25 @@ #ifndef ZOOM_RENDERER_H_ #define ZOOM_RENDERER_H_ -#include "BSPTree.h" #include "gl.h" +#include "BSPTree.h" +#include "Shader.h" + namespace Zoom { class Renderer { public: - Renderer() : activeTexture(0), renderVisitor(this) {} + Renderer(); void render(const BSPTree &tree); template void render(const T &triangles) { + Shader::enable(ambientShader); + glBlendFunc(GL_ONE, GL_ZERO); + glDepthFunc(GL_LEQUAL); + typename T::const_iterator t = triangles.begin(); if(t == triangles.end()) return; @@ -44,6 +50,20 @@ class Renderer { renderTriangle(t->triangle); } 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 { @@ -68,6 +88,7 @@ class Renderer { Renderer *renderer; }; + boost::shared_ptr ambientShader, lightShader; unsigned activeTexture; const RenderVisitor renderVisitor; diff --git a/src/Shader.cpp b/src/Shader.cpp index 420b6c6..545d193 100644 --- a/src/Shader.cpp +++ b/src/Shader.cpp @@ -18,6 +18,7 @@ */ #include "Shader.h" + #include #include #include @@ -25,8 +26,9 @@ namespace Zoom { -bool Shader::loadProgram(const std::string &vertexShader, const std::string &fragmentShader) { +boost::shared_ptr Shader::load(const std::string &vertexShader, const std::string &fragmentShader) { GLhandleARB program, vs = 0, fs = 0; + bool ok = false; if(!vertexShader.empty()) vs = loadShader(vertexShader, GL_VERTEX_SHADER_ARB); @@ -36,25 +38,41 @@ bool Shader::loadProgram(const std::string &vertexShader, const std::string &fra program = glCreateProgramObjectARB(); - if(vs) - glAttachObjectARB(program, vs); + if(program) { + if(vs) + glAttachObjectARB(program, vs); + + if(fs) + glAttachObjectARB(program, fs); - if(fs) - glAttachObjectARB(program, fs); + glLinkProgramARB(program); + if(glGetError()) { + printInfoLog(program); + } + else { + ok = true; + } - glLinkProgramARB(program); - printInfoLog(program); + if(vs) { + glDeleteObjectARB(vs); + } - glUseProgramObjectARB(program); + if(fs) { + glDeleteObjectARB(fs); + } + } - return true; + if(ok) + return boost::shared_ptr(new Shader(program)); + else + return boost::shared_ptr(); } GLhandleARB Shader::loadShader(const std::string &name, GLenum type) { std::vector lines; std::ifstream file(("shader/" + name).c_str(), std::ios_base::in); if(!file.good()) - throw std::ios::failure("Can't read file '" + name + "'"); + return 0; while(file.good() && !file.eof()) { std::string line; @@ -69,12 +87,26 @@ GLhandleARB Shader::loadShader(const std::string &name, GLenum type) { strings[i] = lines[i].c_str(); } + bool ok = false; 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) { diff --git a/src/Shader.h b/src/Shader.h index 8111f0c..e1fdde9 100644 --- a/src/Shader.h +++ b/src/Shader.h @@ -21,19 +21,42 @@ #define ZOOM_SHADER_H_ #include "gl.h" + #include +#include namespace Zoom { class Shader { public: - static bool loadProgram(const std::string &vertexShader, const std::string &fragmentShader); + static boost::shared_ptr load(const std::string &vertexShader, const std::string &fragmentShader); - private: - Shader(); + static void enable(boost::shared_ptr shader) { + if(shader) + glUseProgramObjectARB(shader->handle); + else + glUseProgramObjectARB(0); + } + + static void disable() { + enable(boost::shared_ptr()); + } + + ~Shader() { + glDeleteObjectARB(handle); + } + private: static GLhandleARB loadShader(const std::string &name, GLenum type); static void printInfoLog(GLhandleARB obj); + + Shader(GLhandleARB handle0) : handle(handle0) {} + + // Prevent shallow copy + Shader(const Shader &o); + Shader& operator=(const Shader &o); + + GLhandleARB handle; }; } diff --git a/src/zoom.cpp b/src/zoom.cpp index e0050c5..8193d6a 100644 --- a/src/zoom.cpp +++ b/src/zoom.cpp @@ -22,6 +22,8 @@ #include "config.h" #include "gl.h" +#include + #ifdef _WIN32 #else @@ -69,7 +71,7 @@ bool WGLInit(HINSTANCE hInstance, HWND *hWnd, HDC *hDC, HGLRC *hRC) { if (!RegisterClass(&wc)) { 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; @@ -421,24 +423,29 @@ int main() { case GenericEvent: if(event.xcookie.extension == xi_opcode && XGetEventData(disp, &event.xcookie)) { - XIRawEvent *rawEvent = reinterpret_cast(event.xcookie.data); - - float deltaX = 0, deltaY = 0; - double *rawValuator = rawEvent->raw_values; - - if(XIMaskIsSet(rawEvent->valuators.mask, 0)) { - deltaX = (float)*rawValuator; - ++rawValuator; + switch(event.xcookie.evtype) { + case XI_RawMotion: + XIRawEvent *rawEvent = reinterpret_cast(event.xcookie.data); + + float deltaX = 0, deltaY = 0; + double *rawValuator = rawEvent->raw_values; + + if(rawEvent->valuators.mask_len >= 1) { + if(XIMaskIsSet(rawEvent->valuators.mask, 0)) { + 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); } } -- cgit v1.2.3