Added nice lighting shaders

This commit is contained in:
Matthias Schiffer 2009-12-15 02:25:40 +01:00
parent ff7b7c8838
commit a4fa46a4fd
10 changed files with 283 additions and 34 deletions

View file

@ -5,10 +5,11 @@ set(CMAKE_MODULE_PATH ${ZOOM_SOURCE_DIR})
find_package(Boost REQUIRED) find_package(Boost REQUIRED)
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
find_package(GLPng REQUIRED) find_package(GLPng REQUIRED)
find_package(LibXml2 REQUIRED) find_package(LibXml2 REQUIRED)
include_directories(${Boost_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} ${GLPNG_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}) include_directories(${Boost_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} ${GLEW_INCLUDE_DIR} ${GLPNG_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR})
add_executable(zoom add_executable(zoom
BSPTree.cpp BSPTree.h BSPTree.cpp BSPTree.h
@ -17,9 +18,10 @@ add_executable(zoom
gl.h gl.h
Level.cpp Level.h Level.cpp Level.h
Renderer.cpp Renderer.h Renderer.cpp Renderer.h
Shader.cpp Shader.h
Texture.cpp Texture.h Texture.cpp Texture.h
Triangle.h Triangle.h
zoom.cpp zoom.cpp
) )
target_link_libraries(zoom ${Boost_LIBRARIES} ${OPENGL_LIBRARIES} ${GLPNG_LIBRARY} ${LIBXML2_LIBRARIES}) target_link_libraries(zoom ${Boost_LIBRARIES} ${OPENGL_LIBRARIES} ${GLEW_LIBRARY} ${GLPNG_LIBRARY} ${LIBXML2_LIBRARIES})

16
FindGLEW.cmake Normal file
View file

@ -0,0 +1,16 @@
FIND_PATH(GLEW_INCLUDE_DIR GL/glew.h)
FIND_LIBRARY(GLEW_LIBRARY NAMES GLEW)
IF (GLEW_INCLUDE_DIR AND GLEW_LIBRARY)
SET(GLEW_FOUND TRUE)
ENDIF (GLEW_INCLUDE_DIR AND GLEW_LIBRARY)
IF (GLEW_FOUND)
IF (NOT GLEW_FIND_QUIETLY)
MESSAGE(STATUS "Found GLEW: ${GLEW_LIBRARY}")
ENDIF (NOT GLEW_FIND_QUIETLY)
ELSE (GLEW_FOUND)
IF (GLEW_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find GLEW")
ENDIF (GLEW_FIND_REQUIRED)
ENDIF (GLEW_FOUND)

View file

@ -20,12 +20,13 @@
#include "Game.h" #include "Game.h"
#include "BSPTree.h" #include "BSPTree.h"
#include "Level.h" #include "Level.h"
#include "Shader.h"
#include "Triangle.h" #include "Triangle.h"
#include "gl.h" #include "gl.h"
namespace Zoom { namespace Zoom {
Game::Game(bool multisample) : angle(0) { Game::Game(bool multisample) : angle(0), lightPos(0) {
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);
@ -42,19 +43,23 @@ Game::Game(bool multisample) : angle(0) {
glShadeModel(GL_SMOOTH); glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
static const float light[] = {0, 0, 0, 1}; glLightfv(GL_LIGHT0, GL_AMBIENT, vmml::vec4f::ZERO.array);
static const float lightColor[] = {1, 1, 1, 1}; glLightfv(GL_LIGHT0, GL_DIFFUSE, vmml::vec4f::ONE.array);
glLightfv(GL_LIGHT0, GL_POSITION, light); glLightfv(GL_LIGHT0, GL_SPECULAR, vmml::vec4f::ONE.array);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor); glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0);
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.3);
glEnable(GL_LIGHT0); glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL); glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vmml::vec4f::ONE.array);
glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 128);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW); glFrontFace(GL_CCW);
glLoadIdentity(); Shader::loadProgram("default.vert", "default.frag");
loadLevel("level.xml"); loadLevel("level.xml");
} }
@ -70,21 +75,46 @@ void Game::run(int delta) {
if(angle >= 360) if(angle >= 360)
angle -= 360; angle -= 360;
lightPos += delta;
lightPos %= 24000;
} }
void Game::render() { void Game::render() {
std::list<BSPTree::TriangleRecord> triangles; int i;
float light[] = {0, 0, 0, 1};
triangles.insert(triangles.end(), level->getRooms().front().walls.begin(), level->getRooms().front().walls.end()); if(lightPos < 12000) i = lightPos;
else i = 24000 - lightPos;
if(i < 4000) {
light[0] = 0.0;
light[2] = -i * 0.001;
}
else if(i < 8000) {
light[0] = (i-4000) * 0.001;
light[2] = -4.0;
}
else if(i < 12000) {
light[0] = 4.0;
light[2] = -4.0 - (i-8000) * 0.001;
}
else {
light[0] = 4.0;
light[2] = -8.0;
}
glLightfv(GL_LIGHT0, GL_POSITION, light);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix(); glPushMatrix();
glRotatef(angle, 1, 2, 1); //glRotatef(10, 1, 2, 1);
//glRotatef(3*angle, 0, -1, 2); /*glRotatef(5*angle, 0, -1, 2);
//glRotatef(5*angle, 2, -1, 0); glRotatef(7*angle, 2, -1, 0);
glRotatef(11*angle, 2, -1, 2);*/
renderer.render(triangles); renderer.render(level->getRooms().front().walls);
glPopMatrix(); glPopMatrix();
} }

1
Game.h
View file

@ -43,6 +43,7 @@ class Game {
boost::shared_ptr<Level> level; boost::shared_ptr<Level> level;
float angle; float angle;
int lightPos;
}; };
} }

95
Shader.cpp Normal file
View file

@ -0,0 +1,95 @@
/*
* Shader.cpp
*
* Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Shader.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <boost/scoped_array.hpp>
namespace Zoom {
bool Shader::loadProgram(const std::string &vertexShader, const std::string &fragmentShader) {
GLhandleARB program, vs = 0, fs = 0;
if(!vertexShader.empty())
vs = loadShader(vertexShader, GL_VERTEX_SHADER_ARB);
if(!fragmentShader.empty())
fs = loadShader(fragmentShader, GL_FRAGMENT_SHADER_ARB);
program = glCreateProgramObjectARB();
if(vs)
glAttachObjectARB(program, vs);
if(fs)
glAttachObjectARB(program, fs);
glLinkProgramARB(program);
printInfoLog(program);
glUseProgramObjectARB(program);
return true;
}
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 + "'");
while(file.good() && !file.eof()) {
std::string line;
std::getline(file, line);
if(!line.empty())
lines.push_back(line);
}
boost::scoped_array<const char *> strings(new const char*[lines.size()]);
for(std::size_t i = 0; i < lines.size(); ++i) {
strings[i] = lines[i].c_str();
}
GLhandleARB shader = glCreateShaderObjectARB(type);
glShaderSourceARB(shader, lines.size(), strings.get(), 0);
glCompileShaderARB(shader);
printInfoLog(shader);
return shader;
}
void Shader::printInfoLog(GLhandleARB obj) {
int length = 0;
glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
if(length > 0) {
boost::scoped_array<char> log(new char[length]);
int foo;
glGetInfoLogARB(obj, length, &foo, log.get());
std::cerr << log.get() << std::endl;
}
}
}

41
Shader.h Normal file
View file

@ -0,0 +1,41 @@
/*
* Shader.h
*
* Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ZOOM_SHADER_H_
#define ZOOM_SHADER_H_
#include "gl.h"
#include <string>
namespace Zoom {
class Shader {
public:
static bool loadProgram(const std::string &vertexShader, const std::string &fragmentShader);
private:
Shader();
static GLhandleARB loadShader(const std::string &name, GLenum type);
static void printInfoLog(GLhandleARB obj);
};
}
#endif /* ZOOM_SHADER_H_ */

1
gl.h
View file

@ -25,6 +25,7 @@
#include <windows.h> #include <windows.h>
#endif #endif
#include <GL/glew.h>
#include <GL/gl.h> #include <GL/gl.h>
#include <GL/glu.h> #include <GL/glu.h>

44
shader/default.frag Normal file
View file

@ -0,0 +1,44 @@
uniform sampler2D tex;
varying vec4 diffuse, ambientGlobal, ambient;
varying vec3 normal, pos;
/*varying vec3 normal, lightVector, reflectVector, eyeVector;*/
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;
}

25
shader/default.vert Normal file
View file

@ -0,0 +1,25 @@
varying vec4 diffuse, ambientGlobal, ambient;
varying vec3 normal, pos;
/*varying vec3 normal, lightVector, reflectVector, eyeVector;*/
void main() {
normal = normalize(gl_NormalMatrix * gl_Normal);
pos = vec3(gl_ModelViewMatrix * gl_Vertex);
/*lightVector = vec3(gl_LightSource[0].position - ecPos);
reflectVector = normalize(reflect(-lightVector, normal));
eyeVector = vec3(-ecPos);*/
/* Compute the diffuse, ambient and globalAmbient terms */
diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;
/* The ambient terms have been separated since one of them */
/* suffers attenuation */
ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
ambientGlobal = gl_LightModel.ambient * gl_FrontMaterial.ambient;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}

View file

@ -66,8 +66,7 @@ bool WGLInit(HINSTANCE hInstance, HWND *hWnd, HDC *hDC, HGLRC *hRC) {
wc.lpszMenuName = 0; wc.lpszMenuName = 0;
wc.lpszClassName = "3D"; wc.lpszClassName = "3D";
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; // Exit And Return FALSE
} }
@ -85,14 +84,12 @@ bool WGLInit(HINSTANCE hInstance, HWND *hWnd, HDC *hDC, HGLRC *hRC) {
*hWnd = CreateWindowEx(dwExStyle, "3D" /* Class Name */, "3D" /* Title*/, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dwStyle, *hWnd = CreateWindowEx(dwExStyle, "3D" /* Class Name */, "3D" /* Title*/, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dwStyle,
0, 0, windowRect.right-windowRect.left, windowRect.bottom-windowRect.top, 0, 0, hInstance, 0); 0, 0, windowRect.right-windowRect.left, windowRect.bottom-windowRect.top, 0, 0, hInstance, 0);
if(!*hWnd) if(!*hWnd) {
{
MessageBox(0, "Window Creation Error.", "ERROR", MB_OK|MB_ICONEXCLAMATION); MessageBox(0, "Window Creation Error.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
return false; return false;
} }
static PIXELFORMATDESCRIPTOR pfd = static PIXELFORMATDESCRIPTOR pfd = {
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number 1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window PFD_DRAW_TO_WINDOW | // Format Must Support Window
@ -114,38 +111,33 @@ bool WGLInit(HINSTANCE hInstance, HWND *hWnd, HDC *hDC, HGLRC *hRC) {
}; };
*hDC=GetDC(*hWnd); *hDC=GetDC(*hWnd);
if (!*hDC) if (!*hDC) {
{
WGLUninit(*hWnd, 0, 0); WGLUninit(*hWnd, 0, 0);
MessageBox(0, "Can't Create A GL Device Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION); MessageBox(0, "Can't Create A GL Device Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
return false; return false;
} }
GLuint pixelFormat = ChoosePixelFormat(*hDC, &pfd); GLuint pixelFormat = ChoosePixelFormat(*hDC, &pfd);
if(!pixelFormat) if(!pixelFormat) {
{
WGLUninit(*hWnd, *hDC, 0); WGLUninit(*hWnd, *hDC, 0);
MessageBox(0, "Can't Find A Suitable PixelFormat.", "ERROR", MB_OK|MB_ICONEXCLAMATION); MessageBox(0, "Can't Find A Suitable PixelFormat.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
return false; return false;
} }
if(!SetPixelFormat(*hDC, pixelFormat, &pfd)) if(!SetPixelFormat(*hDC, pixelFormat, &pfd)) {
{
WGLUninit(*hWnd, *hDC, 0); WGLUninit(*hWnd, *hDC, 0);
MessageBox(0, "Can't Set The PixelFormat.", "ERROR", MB_OK|MB_ICONEXCLAMATION); MessageBox(0, "Can't Set The PixelFormat.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
return false; return false;
} }
*hRC=wglCreateContext(*hDC); *hRC=wglCreateContext(*hDC);
if(!*hRC) if(!*hRC) {
{
WGLUninit(*hWnd, *hDC, 0); WGLUninit(*hWnd, *hDC, 0);
MessageBox(0, "Can't Create A GL Rendering Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION); MessageBox(0, "Can't Create A GL Rendering Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
return false; return false;
} }
if(!wglMakeCurrent(*hDC, *hRC)) if(!wglMakeCurrent(*hDC, *hRC)) {
{
WGLUninit(*hWnd, *hDC, *hRC); WGLUninit(*hWnd, *hDC, *hRC);
MessageBox(0, "Can't Activate The GL Rendering Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION); MessageBox(0, "Can't Activate The GL Rendering Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
return false; return false;
@ -171,17 +163,17 @@ void WGLUninit(HWND hWnd, HDC hDC, HGLRC hRC) {
DestroyWindow(hWnd); DestroyWindow(hWnd);
} }
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
{
HWND hWnd = 0; HWND hWnd = 0;
HDC hDC = 0; HDC hDC = 0;
HGLRC hRC = 0; HGLRC hRC = 0;
if(!WGLInit(hInstance, &hWnd, &hDC, &hRC)) if(!WGLInit(hInstance, &hWnd, &hDC, &hRC)) {
{
return 0; return 0;
} }
glewInit();
resize(DEFAULT_WIDTH, DEFAULT_HEIGHT); resize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
bool running = true; bool running = true;
@ -330,6 +322,8 @@ int main() {
if(!GLXinit(disp, windele, &wnd, &gc, &multisample)) if(!GLXinit(disp, windele, &wnd, &gc, &multisample))
return 1; return 1;
glewInit();
resize(DEFAULT_WIDTH, DEFAULT_HEIGHT); resize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
Zoom::Game game(multisample); Zoom::Game game(multisample);