Use multi-pass rendering with seperate ambient and light shaders
This commit is contained in:
parent
b3b74dc2af
commit
4e3efa239c
10 changed files with 148 additions and 48 deletions
8
shader/ambient.frag
Normal file
8
shader/ambient.frag
Normal 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
8
shader/ambient.vert
Normal 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();
|
||||||
|
}
|
|
@ -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;
|
|
||||||
}
|
}
|
|
@ -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();
|
|
@ -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());
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
29
src/Shader.h
29
src/Shader.h
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
37
src/zoom.cpp
37
src/zoom.cpp
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue