summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <matthias@gamezock.de>2009-12-15 02:25:40 +0100
committerMatthias Schiffer <matthias@gamezock.de>2009-12-15 02:25:40 +0100
commita4fa46a4fda967348ea18961c177330491bdb953 (patch)
treeebb601c9c03e9939bf681d740342c38d14c0848f
parentff7b7c8838f55dc0f2e76f903630f1d3d2941d5a (diff)
downloadzoom++-a4fa46a4fda967348ea18961c177330491bdb953.tar
zoom++-a4fa46a4fda967348ea18961c177330491bdb953.zip
Added nice lighting shaders
-rw-r--r--CMakeLists.txt6
-rw-r--r--FindGLEW.cmake16
-rw-r--r--Game.cpp54
-rw-r--r--Game.h1
-rw-r--r--Shader.cpp95
-rw-r--r--Shader.h41
-rw-r--r--gl.h1
-rw-r--r--shader/default.frag44
-rw-r--r--shader/default.vert25
-rw-r--r--zoom.cpp34
10 files changed, 283 insertions, 34 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6135c41..305c938 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,10 +5,11 @@ set(CMAKE_MODULE_PATH ${ZOOM_SOURCE_DIR})
find_package(Boost REQUIRED)
find_package(OpenGL REQUIRED)
+find_package(GLEW REQUIRED)
find_package(GLPng 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
BSPTree.cpp BSPTree.h
@@ -17,9 +18,10 @@ add_executable(zoom
gl.h
Level.cpp Level.h
Renderer.cpp Renderer.h
+ Shader.cpp Shader.h
Texture.cpp Texture.h
Triangle.h
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})
diff --git a/FindGLEW.cmake b/FindGLEW.cmake
new file mode 100644
index 0000000..cf743e0
--- /dev/null
+++ b/FindGLEW.cmake
@@ -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)
diff --git a/Game.cpp b/Game.cpp
index 46f942f..d948b2f 100644
--- a/Game.cpp
+++ b/Game.cpp
@@ -20,12 +20,13 @@
#include "Game.h"
#include "BSPTree.h"
#include "Level.h"
+#include "Shader.h"
#include "Triangle.h"
#include "gl.h"
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);
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
@@ -42,19 +43,23 @@ Game::Game(bool multisample) : angle(0) {
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
- static const float light[] = {0, 0, 0, 1};
- static const float lightColor[] = {1, 1, 1, 1};
- glLightfv(GL_LIGHT0, GL_POSITION, light);
- glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor);
+ glLightfv(GL_LIGHT0, GL_AMBIENT, vmml::vec4f::ZERO.array);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, vmml::vec4f::ONE.array);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, vmml::vec4f::ONE.array);
+ glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0);
+ glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.3);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
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);
glFrontFace(GL_CCW);
- glLoadIdentity();
+ Shader::loadProgram("default.vert", "default.frag");
loadLevel("level.xml");
}
@@ -70,21 +75,46 @@ void Game::run(int delta) {
if(angle >= 360)
angle -= 360;
+
+ lightPos += delta;
+ lightPos %= 24000;
}
void Game::render() {
- std::list<BSPTree::TriangleRecord> triangles;
+ int i;
+ float light[] = {0, 0, 0, 1};
+
+ 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;
+ }
- triangles.insert(triangles.end(), level->getRooms().front().walls.begin(), level->getRooms().front().walls.end());
+ glLightfv(GL_LIGHT0, GL_POSITION, light);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
- glRotatef(angle, 1, 2, 1);
- //glRotatef(3*angle, 0, -1, 2);
- //glRotatef(5*angle, 2, -1, 0);
+ //glRotatef(10, 1, 2, 1);
+ /*glRotatef(5*angle, 0, -1, 2);
+ glRotatef(7*angle, 2, -1, 0);
+ glRotatef(11*angle, 2, -1, 2);*/
- renderer.render(triangles);
+ renderer.render(level->getRooms().front().walls);
glPopMatrix();
}
diff --git a/Game.h b/Game.h
index 7960497..f651125 100644
--- a/Game.h
+++ b/Game.h
@@ -43,6 +43,7 @@ class Game {
boost::shared_ptr<Level> level;
float angle;
+ int lightPos;
};
}
diff --git a/Shader.cpp b/Shader.cpp
new file mode 100644
index 0000000..420b6c6
--- /dev/null
+++ b/Shader.cpp
@@ -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;
+ }
+}
+
+
+}
diff --git a/Shader.h b/Shader.h
new file mode 100644
index 0000000..8111f0c
--- /dev/null
+++ b/Shader.h
@@ -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_ */
diff --git a/gl.h b/gl.h
index 22e0523..3272b25 100644
--- a/gl.h
+++ b/gl.h
@@ -25,6 +25,7 @@
#include <windows.h>
#endif
+#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glu.h>
diff --git a/shader/default.frag b/shader/default.frag
new file mode 100644
index 0000000..b39b46d
--- /dev/null
+++ b/shader/default.frag
@@ -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;
+}
diff --git a/shader/default.vert b/shader/default.vert
new file mode 100644
index 0000000..133c871
--- /dev/null
+++ b/shader/default.vert
@@ -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();
+}
diff --git a/zoom.cpp b/zoom.cpp
index 8f01c1b..6fab527 100644
--- a/zoom.cpp
+++ b/zoom.cpp
@@ -66,8 +66,7 @@ bool WGLInit(HINSTANCE hInstance, HWND *hWnd, HDC *hDC, HGLRC *hRC) {
wc.lpszMenuName = 0;
wc.lpszClassName = "3D";
- if (!RegisterClass(&wc))
- {
+ if (!RegisterClass(&wc)) {
MessageBox(0, "Failed To Register The Window Class.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
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,
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);
return false;
}
- static PIXELFORMATDESCRIPTOR pfd =
- {
+ static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
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);
- if (!*hDC)
- {
+ if (!*hDC) {
WGLUninit(*hWnd, 0, 0);
MessageBox(0, "Can't Create A GL Device Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
return false;
}
GLuint pixelFormat = ChoosePixelFormat(*hDC, &pfd);
- if(!pixelFormat)
- {
+ if(!pixelFormat) {
WGLUninit(*hWnd, *hDC, 0);
MessageBox(0, "Can't Find A Suitable PixelFormat.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
return false;
}
- if(!SetPixelFormat(*hDC, pixelFormat, &pfd))
- {
+ if(!SetPixelFormat(*hDC, pixelFormat, &pfd)) {
WGLUninit(*hWnd, *hDC, 0);
MessageBox(0, "Can't Set The PixelFormat.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
return false;
}
*hRC=wglCreateContext(*hDC);
- if(!*hRC)
- {
+ if(!*hRC) {
WGLUninit(*hWnd, *hDC, 0);
MessageBox(0, "Can't Create A GL Rendering Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
return false;
}
- if(!wglMakeCurrent(*hDC, *hRC))
- {
+ if(!wglMakeCurrent(*hDC, *hRC)) {
WGLUninit(*hWnd, *hDC, *hRC);
MessageBox(0, "Can't Activate The GL Rendering Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
return false;
@@ -171,17 +163,17 @@ void WGLUninit(HWND hWnd, HDC hDC, HGLRC hRC) {
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;
HDC hDC = 0;
HGLRC hRC = 0;
- if(!WGLInit(hInstance, &hWnd, &hDC, &hRC))
- {
+ if(!WGLInit(hInstance, &hWnd, &hDC, &hRC)) {
return 0;
}
+ glewInit();
+
resize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
bool running = true;
@@ -330,6 +322,8 @@ int main() {
if(!GLXinit(disp, windele, &wnd, &gc, &multisample))
return 1;
+ glewInit();
+
resize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
Zoom::Game game(multisample);