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;
|
||||
|
||||
varying vec4 diffuse, ambientGlobal, ambient;
|
||||
varying vec4 diffuse, ambient;
|
||||
varying vec3 normal, pos;
|
||||
|
||||
|
||||
|
@ -10,8 +10,6 @@ void main() {
|
|||
vec4 color, specularColor;
|
||||
float dist, att, specularFactor;
|
||||
|
||||
color = ambientGlobal;
|
||||
|
||||
n = normalize(normal);
|
||||
|
||||
l = gl_LightSource[0].position.xyz - pos;
|
||||
|
@ -26,7 +24,7 @@ void main() {
|
|||
att = 1.0 / (gl_LightSource[0].constantAttenuation +
|
||||
gl_LightSource[0].linearAttenuation * dist +
|
||||
gl_LightSource[0].quadraticAttenuation * dist * dist);
|
||||
color += att * (diffuse * NdotL + ambient);
|
||||
color = att * (diffuse * NdotL + ambient);
|
||||
|
||||
refl = normalize(reflect(-l, n));
|
||||
eye = normalize(-pos);
|
||||
|
@ -34,10 +32,10 @@ void main() {
|
|||
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;
|
||||
}
|
||||
else {
|
||||
gl_FragColor = vec4(0, 0, 0, 1);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
varying vec4 diffuse, ambientGlobal, ambient;
|
||||
varying vec4 diffuse, ambient;
|
||||
varying vec3 normal, pos;
|
||||
|
||||
|
||||
|
@ -10,7 +10,6 @@ void main() {
|
|||
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();
|
|
@ -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());
|
||||
|
|
|
@ -18,9 +18,15 @@
|
|||
*/
|
||||
|
||||
#include "Renderer.h"
|
||||
#include "Shader.h"
|
||||
|
||||
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) {
|
||||
vmml::mat4f transform, inverseTransform;
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, transform.array);
|
||||
|
|
|
@ -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 <typename T>
|
||||
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<Shader> ambientShader, lightShader;
|
||||
unsigned activeTexture;
|
||||
|
||||
const RenderVisitor renderVisitor;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include "Shader.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
@ -25,8 +26,9 @@
|
|||
|
||||
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;
|
||||
bool ok = false;
|
||||
|
||||
if(!vertexShader.empty())
|
||||
vs = loadShader(vertexShader, GL_VERTEX_SHADER_ARB);
|
||||
|
@ -36,6 +38,7 @@ bool Shader::loadProgram(const std::string &vertexShader, const std::string &fra
|
|||
|
||||
program = glCreateProgramObjectARB();
|
||||
|
||||
if(program) {
|
||||
if(vs)
|
||||
glAttachObjectARB(program, vs);
|
||||
|
||||
|
@ -43,18 +46,33 @@ bool Shader::loadProgram(const std::string &vertexShader, const std::string &fra
|
|||
glAttachObjectARB(program, fs);
|
||||
|
||||
glLinkProgramARB(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) {
|
||||
std::vector<std::string> 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);
|
||||
|
||||
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) {
|
||||
|
|
29
src/Shader.h
29
src/Shader.h
|
@ -21,19 +21,42 @@
|
|||
#define ZOOM_SHADER_H_
|
||||
|
||||
#include "gl.h"
|
||||
|
||||
#include <string>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace Zoom {
|
||||
|
||||
class Shader {
|
||||
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:
|
||||
Shader();
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "config.h"
|
||||
#include "gl.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
#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,11 +423,14 @@ int main() {
|
|||
|
||||
case GenericEvent:
|
||||
if(event.xcookie.extension == xi_opcode && XGetEventData(disp, &event.xcookie)) {
|
||||
switch(event.xcookie.evtype) {
|
||||
case XI_RawMotion:
|
||||
XIRawEvent *rawEvent = reinterpret_cast<XIRawEvent*>(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;
|
||||
|
@ -435,9 +440,11 @@ int main() {
|
|||
deltaY = (float)*rawValuator;
|
||||
++rawValuator;
|
||||
}
|
||||
}
|
||||
|
||||
if(deltaX != 0 || deltaY != 0)
|
||||
game.turn(deltaX, deltaY);
|
||||
}
|
||||
|
||||
XFreeEventData(disp, &event.xcookie);
|
||||
}
|
||||
|
|
Reference in a new issue