]> git.lizzy.rs Git - shadowclad.git/blob - src/engine/render.c
Add copyright and license notices in source code
[shadowclad.git] / src / engine / render.c
1 /**
2  * Copyright 2018-2020 Iwo 'Outfrost' Bujkiewicz
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  */
8
9 #include "render.h"
10
11 #include "geometry.h"
12 #include "performance.h"
13
14 #include "game/player.h"
15
16 float viewportAspectRatio = 1.0f;
17 const Scene* cameraAnchor;
18 bool debugScene = false;
19 bool debugRender = false;
20
21 static const float AXIS_RADIUS = 5.0f;
22
23 static void renderScene(const Scene*, const Transform baseTransform);
24 static void setupCamera();
25 static void moveCameraTo(const Scene* scene);
26 static void drawAxes();
27 static void drawSolid(const Solid* solid);
28
29
30
31 void initRender() {
32         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
33
34         GLfloat light0_ambient[] = {0.1f, 0.1f, 0.1f, 1.0f};
35         GLfloat light0_diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
36         GLfloat light0_specular[] = {0.96f, 0.98f, 1.0f, 1.0f};
37         GLfloat light0_position[] = {5.0f, 10.0f, 5.0f, 0.0f}; // (w == 0.0f) == directional
38
39         glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
40         glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
41         glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
42         glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
43
44         glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0f);
45         glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05f);
46         glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.005f);
47
48         //glShadeModel(GL_FLAT);
49 }
50
51 void renderFrame(GLFWwindow* window) {
52         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
53
54         glEnable(GL_NORMALIZE);
55         glEnable(GL_CULL_FACE);
56         glEnable(GL_DEPTH_TEST);
57
58         setupCamera();
59         moveCameraTo(cameraAnchor);
60
61         renderScene(currentScene, identity());
62
63         glFlush();
64         glfwSwapBuffers(window);
65         frameRendered();
66 }
67
68 static void renderScene(const Scene* scene, const Transform baseTransform) {
69         if (!scene) {
70                 return;
71         }
72
73         Transform transform = multiply(scene->transform, baseTransform);
74
75         glMatrixMode(GL_MODELVIEW);
76         glLoadTransposeMatrixf((const GLfloat*) &transform);
77
78         glDisable(GL_LIGHTING);
79
80         if (debugScene || scene == playerProjectedMovement) {
81                 drawAxes();
82         }
83
84         glEnable(GL_LIGHTING);
85
86         if (scene->solid) {
87                 glEnable(GL_LIGHT0);
88                 glEnable(GL_TEXTURE_2D);
89                 drawSolid(scene->solid);
90                 glDisable(GL_TEXTURE_2D);
91                 glDisable(GL_LIGHT0);
92         }
93
94         for (size_t i = 0; i < scene->numChildren; ++i) {
95                 renderScene(scene->children[i], transform);
96         }
97 }
98
99 static void setupCamera() {
100         glMatrixMode(GL_PROJECTION);
101         glLoadIdentity();
102         glOrtho(-16.0,
103                 16.0,
104                 -16.0/viewportAspectRatio,
105                 16.0/viewportAspectRatio,
106                 -128.0,
107                 128.0);
108         glRotatef(45.0f, 1.0f, 0.0f, 0.0f);
109         glRotatef(45.0f, 0.0f, 1.0f, 0.0f);
110 }
111
112 static void moveCameraTo(const Scene* anchor) {
113         glMatrixMode(GL_PROJECTION);
114         Vector pos = translationOf(worldTransform(anchor));
115         glTranslatef(-pos.x, -pos.y, -pos.z);
116 }
117
118 static void drawAxes() {
119         glMatrixMode(GL_MODELVIEW);
120         // X axis
121         glColor3f(1.0f, 0.0f, 0.0f);
122         glBegin(GL_LINES);
123         glVertex3f(0.0f, 0.0f, 0.0f);
124         glVertex3f(AXIS_RADIUS, 0.0f, 0.0f);
125         glEnd();
126         // Y axis
127         glColor3f(0.0f, 1.0f, 0.0f);
128         glBegin(GL_LINES);
129         glVertex3f(0.0f, 0.0f, 0.0f);
130         glVertex3f(0.0f, AXIS_RADIUS, 0.0f);
131         glEnd();
132         // Z axis
133         glColor3f(0.0f, 0.0f, 1.0f);
134         glBegin(GL_LINES);
135         glVertex3f(0.0f, 0.0f, 0.0f);
136         glVertex3f(0.0f, 0.0f, AXIS_RADIUS);
137         glEnd();
138 }
139
140 static GLfloat absolute(GLfloat a) {
141         return a < 0 ? -a : a;
142 }
143
144 static void drawSolid(const Solid* solid) {
145         if (solid == NULL) {
146                 return;
147         }
148
149         glMatrixMode(GL_MODELVIEW);
150         glColor3f(0.5f, 1.0f, 0.0f);
151
152         for (size_t meshIndex = 0; meshIndex < solid->numMeshes; ++meshIndex) {
153                 const Mesh mesh = solid->meshes[meshIndex];
154                 glBindTexture(GL_TEXTURE_2D,
155                               solid->materials[mesh.materialIndex].textureId);
156
157                 for (size_t faceIndex = 0; faceIndex < mesh.numFaces; ++faceIndex) {
158                         const Face face = mesh.faces[faceIndex];
159
160                         if (debugRender && face.normals) {
161                                 glDisable(GL_LIGHTING);
162                                 glDisable(GL_TEXTURE_2D);
163                                 glBegin(GL_LINES);
164                                 for (size_t i = 0; i < face.numIndices; ++i) {
165                                         size_t vertIndex = face.indices[i];
166                                         Vector vertex = mesh.vertices[vertIndex];
167                                         Vector normal = face.normals[i];
168                                         glColor3f(absolute(normal.x), absolute(normal.y), absolute(normal.z));
169                                         glVertex3f(vertex.x, vertex.y, vertex.z);
170                                         glVertex3f(vertex.x + normal.x, vertex.y + normal.y, vertex.z + normal.z);
171                                 }
172                                 glEnd();
173                                 glEnable(GL_TEXTURE_2D);
174                                 glEnable(GL_LIGHTING);
175                         }
176
177                         GLenum faceMode;
178                         switch (face.numIndices) {
179                                 case 1: faceMode = GL_POINTS; break;
180                                 case 2: faceMode = GL_LINES; break;
181                                 case 3: faceMode = GL_TRIANGLES; break;
182                                 default: faceMode = GL_POLYGON; break;
183                         }
184
185                         glBegin(faceMode);
186
187                         for (size_t i = 0; i < face.numIndices; ++i) {
188                                 size_t vertIndex = face.indices[i];
189                                 if (face.normals) {
190                                         if (mesh.textureCoords) {
191                                                 Vector coords = mesh.textureCoords[vertIndex];
192                                                 glTexCoord2f(coords.x, coords.y);
193                                         }
194                                         Vector normal = face.normals[i];
195                                         glNormal3f(normal.x, normal.y, normal.z);
196                                 }
197
198                                 Vector vertex = mesh.vertices[vertIndex];
199                                 glVertex3f(vertex.x, vertex.y, vertex.z);
200                         }
201
202                         glEnd();
203                 }
204         }
205         glBindTexture(GL_TEXTURE_2D, 0);
206 }