-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.c
233 lines (181 loc) · 7.99 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include "raster/graphics.h"
#include "raster/renderer.h"
#include "job_system/js.h"
#include "raster/light.h"
#include "utils/mat4x4.h"
#include "utils/utils.h"
// TODO : Fix jobs full error
static inline void BindVertexBuffer(void *vertex_buffer, const size_t length, const size_t stride)
{
ASSERT(vertex_buffer);
ASSERT(stride > 0);
RenderState.vertex_buffer = vertex_buffer;
RenderState.vertex_stride = stride;
RenderState.vertex_buffer_length = length;
}
static inline void BindIndexBuffer(int *index_buffer, const size_t length)
{
ASSERT(index_buffer);
ASSERT(length > 0);
RenderState.index_buffer = index_buffer;
RenderState.index_buffer_length = length;
}
void Convert_Depth_Buffer_For_Drawing(void)
{
// Define the minimum and maximum depth values in your depth buffer
const float minDepth = 0.0f /* Set the minimum depth value */;
const float maxDepth = 10.0f /* Set the maximum depth value */;
#if 0
// Iterate over each depth value in the depth buffer
for (size_t i = 0; i < IMAGE_W * IMAGE_H; ++i)
{
const float depthValue = RenderState.depth_buffer[i];
if (depthValue == FLT_MAX)
continue;
// Normalize the depth value between 0 and 1
const float normalizedDepth = ((depthValue - minDepth) / (maxDepth - minDepth));
// Map the normalized depth value to the range of 0 to 255
const uint8_t colorValue = (uint8_t)(normalizedDepth * 255.0f);
// Assign the color value to the RGBA color buffer
RenderState.colour_buffer[i * 4 + 0] = colorValue; // Red component
RenderState.colour_buffer[i * 4 + 1] = colorValue; // Green component
RenderState.colour_buffer[i * 4 + 2] = colorValue; // Blue component
RenderState.colour_buffer[i * 4 + 3] = 255; // Alpha component (fully opaque)
}
#else
// Load the minimum and maximum depth values into SIMD registers
__m128 minDepthVec = _mm_set1_ps(minDepth);
__m128 maxDepthVec = _mm_set1_ps(maxDepth);
// Iterate over each depth value in the depth buffer (processing 4 values at a time)
for (size_t i = 0; i < IMAGE_W * IMAGE_H; i += 4)
{
// Load 4 depth values from the depth buffer into a SIMD register
__m128 depthVec = _mm_load_ps(&RenderState.depth_buffer[i]);
__m128 cmp = _mm_cmpeq_ps(depthVec, _mm_set1_ps(FLT_MAX));
if (_mm_testz_si128(_mm_cvtps_epi32(cmp), _mm_cvtps_epi32(cmp)) == 0)
continue;
// Normalize the depth values between 0 and 1
__m128 normalizedDepthVec = _mm_div_ps(_mm_sub_ps(depthVec, minDepthVec), _mm_sub_ps(maxDepthVec, minDepthVec));
// Map the normalized depth values to the range of 0 to 255
__m128i colorValueVec = _mm_cvtps_epi32(_mm_mul_ps(normalizedDepthVec, _mm_set1_ps(255.0f)));
// Convert the packed integer values to 8-bit unsigned integers
__m128i colorValueU8Vec = _mm_packus_epi32(colorValueVec, colorValueVec);
colorValueU8Vec = _mm_packus_epi16(colorValueU8Vec, colorValueU8Vec);
// Store the color values into the RGBA color buffer
_mm_storeu_si128((__m128i *)&RenderState.colour_buffer[i], colorValueU8Vec);
}
#endif
}
int main(int argc, char *argv[])
{
argc = 0;
argv = NULL;
DEBUG_MODE_PRINT;
if (!Reneder_Startup("Simderella", IMAGE_W, IMAGE_H))
return EXIT_FAILURE;
jobs_init();
/* Load a object */
struct Mesh obj = Mesh_Load("../../res/Wooden Box/wooden crate.obj");
// struct Mesh obj = Mesh_Load("../../res/Teapot/teapot.obj");
// struct Mesh obj = Mesh_Load("../../res/sponza/sponza.obj"); // Big boy
// struct Mesh obj = Mesh_Load("../../res/sponza_small/sponza.obj"); // Big boy
// struct Mesh obj = Mesh_Load("../../res/dragon.obj"); // Big boy
vec3 cam_position = {0.0f, 0.0f, 3.5f};
mat4x4 view, proj;
Raster_View_Matrix(view, cam_position);
Raster_Projection_Matrix(proj, IMAGE_W, IMAGE_H);
timer_t rasterizer_timer;
Timer_Start(&rasterizer_timer);
// Side quest to get vertex index data...
float *vertex_data = malloc(sizeof(float) * obj.attribute.num_faces * 5); // 3 for vert, 2 for tex
int *index_data = malloc(sizeof(int) * obj.attribute.num_faces);
for (size_t i = 0; i < obj.attribute.num_faces; i++)
{
tinyobj_vertex_index_t face = obj.attribute.faces[i];
index_data[i] = (int)i; // NOTE : We are not setting unique indices
vertex_data[i * 5 + 0] = obj.attribute.vertices[face.v_idx * 3 + 0];
vertex_data[i * 5 + 1] = obj.attribute.vertices[face.v_idx * 3 + 1];
vertex_data[i * 5 + 2] = obj.attribute.vertices[face.v_idx * 3 + 2];
vertex_data[i * 5 + 3] = obj.attribute.texcoords[face.vt_idx * 2 + 0];
vertex_data[i * 5 + 4] = obj.attribute.texcoords[face.vt_idx * 2 + 1];
}
/* Convert obj format to {posX, posY, posZ}{texU, texV} */
UniformData_t uniform_data = {0};
uniform_data.diffuse = obj.diffuse_tex;
RenderState.vertex_shader_uniforms = (void *)&uniform_data;
BindIndexBuffer(index_data, obj.attribute.num_faces);
BindVertexBuffer((void *)vertex_data, obj.attribute.num_faces * 5, 5);
Render_Set_Viewport(IMAGE_W, IMAGE_H);
float fTheta = 0.0f;
bool render_depth_buffer = false;
double frame_accumulated_time = 0.0;
uint32_t frame_counter = 0;
while (global_renderer.running)
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
if ((SDL_QUIT == event.type) ||
(SDL_KEYDOWN == event.type && SDL_SCANCODE_ESCAPE == event.key.keysym.scancode))
{
global_renderer.running = false;
break;
}
if (SDL_KEYDOWN == event.type && SDL_SCANCODE_D == event.key.keysym.scancode)
{
render_depth_buffer = !render_depth_buffer;
break;
}
}
fTheta += (float)Timer_Get_Elapsed_MS(&rasterizer_timer) / 32.0f;
// Update the MVP matrix for the Vertex Shader
mat4x4 model = {0};
dash_translate_make(model, 0.0f, 0.0f, 0.0f);
dash_rotate(model, glm_rad(30.0f), (vec3){0.0f, 1.0f, 0.0f});
// dash_rotate(model, glm_rad(fTheta), (vec3){0.0f, 1.0f, 0.0f});
dash_mat_mul_mat(view, model, uniform_data.MVP);
dash_mat_mul_mat(proj, uniform_data.MVP, uniform_data.MVP);
/* Update Scene here */
Setup_Triangles_For_MT();
Raster_Triangles_MT();
// Update the pixels of the surface with the color buffer data
ASSERT(global_renderer.screen_num_pixels == IMAGE_W * IMAGE_H * IMAGE_BPP);
if (render_depth_buffer) /* Draw Depth buffer */
Convert_Depth_Buffer_For_Drawing();
/* Draw Colour buffer */
#ifdef GRAPHICS_USE_SDL_RENDERER
SDL_UpdateTexture(global_renderer.texture, NULL, RenderState.colour_buffer, IMAGE_W * IMAGE_BPP);
SDL_RenderCopy(global_renderer.renderer, global_renderer.texture, NULL, NULL);
SDL_RenderPresent(global_renderer.renderer);
#else
memcpy_s(global_renderer.pixels, global_renderer.screen_num_pixels, RenderState.colour_buffer, IMAGE_W * IMAGE_H * IMAGE_BPP);
SDL_UpdateWindowSurface(global_renderer.window);
#endif
Timer_Update(&rasterizer_timer);
if (frame_counter >= 120)
{
char buff[16] = {0};
sprintf_s(buff, 16, "%fms", frame_accumulated_time / frame_counter);
Renderer_Set_Title(buff);
frame_counter = 0;
frame_accumulated_time = 0.0;
}
else
{
frame_accumulated_time += Timer_Get_Elapsed_MS(&rasterizer_timer);
frame_counter++;
}
}
free(index_data);
free(vertex_data);
Mesh_Destroy(&obj);
Renderer_Destroy();
jobs_shutdown();
printf("EXIT_SUCCESS\n");
return EXIT_SUCCESS;
}