Compare commits
No commits in common. "d01a33e27cea95ae96cb90004769e7f48ed678a2" and "9529b89127c7fc123236b7dfe81aa8a77eb6f862" have entirely different histories.
d01a33e27c
...
9529b89127
109
CMakeLists.txt
109
CMakeLists.txt
@ -1,74 +1,9 @@
|
|||||||
cmake_minimum_required(VERSION 4.0)
|
cmake_minimum_required(VERSION 3.22)
|
||||||
project(sdl_project)
|
project(sdl_project)
|
||||||
set(CMAKE_C_STANDARD 23)
|
|
||||||
|
|
||||||
# Include the command that downloads libraries
|
set(CMAKE_C_STANDARD 11)
|
||||||
include(FetchContent)
|
|
||||||
|
|
||||||
# define a function for adding git dependencies
|
|
||||||
function(include_dependency libName gitURL gitTag)
|
|
||||||
FetchContent_Declare(${libName}
|
|
||||||
GIT_REPOSITORY ${gitURL}
|
|
||||||
GIT_TAG ${gitTag}
|
|
||||||
GIT_SHALLOW TRUE
|
|
||||||
GIT_PROGRESS TRUE
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(${libName})
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# add SDL2 support
|
|
||||||
find_package(SDL2 QUIET)
|
|
||||||
if (NOT SDL2_FOUND)
|
|
||||||
message(STATUS "Getting SDL2 from Github")
|
|
||||||
include_dependency(SDL2 https://github.com/libsdl-org/SDL.git release-2.30.8)
|
|
||||||
else()
|
|
||||||
message(STATUS "Using local SDL2")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# add SDL2_image support
|
|
||||||
find_package(SDL2_image QUIET)
|
|
||||||
if (NOT SDL2_image_FOUND)
|
|
||||||
message(STATUS "Getting SDL2_image from Github")
|
|
||||||
include_dependency(SDL2_image https://github.com/libsdl-org/SDL_image.git release-2.8.2)
|
|
||||||
else()
|
|
||||||
message(STATUS "Using local SDL2_image")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
## add SDL2_gfx support (NO find_package, fetch and add it manually)
|
|
||||||
#find_package(SDL2_gfx QUIET)
|
|
||||||
#if (NOT SDL2_gfx)
|
|
||||||
# message(STATUS "Getting SDL2_gfx from Github")
|
|
||||||
# include_dependency(SDL2_gfx https://github.com/giroletm/SDL2_gfx.git release-1.0.4)
|
|
||||||
#else()
|
|
||||||
# message(STATUS "Using local SDL2_gfx")
|
|
||||||
#endif()
|
|
||||||
|
|
||||||
# SDL2_gfx (DO NOT use the function for this one)
|
|
||||||
FetchContent_Declare(
|
|
||||||
SDL2_gfx
|
|
||||||
GIT_REPOSITORY https://github.com/giroletm/SDL2_gfx.git
|
|
||||||
GIT_TAG master
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(SDL2_gfx)
|
|
||||||
message(STATUS "sdl2_gfx_SOURCE_DIR is: ${sdl2_gfx_SOURCE_DIR}")
|
|
||||||
add_library(SDL2_gfx STATIC
|
|
||||||
${sdl2_gfx_SOURCE_DIR}/SDL2_gfxPrimitives.c
|
|
||||||
${sdl2_gfx_SOURCE_DIR}/SDL2_rotozoom.c
|
|
||||||
)
|
|
||||||
|
|
||||||
target_include_directories(SDL2_gfx PUBLIC ${sdl2_gfx_SOURCE_DIR}/sdl2_gfx-src)
|
|
||||||
target_link_libraries(SDL2_gfx PUBLIC SDL2::SDL2)
|
|
||||||
|
|
||||||
# add SDL2_ttf support
|
|
||||||
#set(SDL2TTF_VENDORED ON)
|
|
||||||
#find_package(SDL2_ttf QUIET)
|
|
||||||
#if (NOT SDL2_ttf_FOUND)
|
|
||||||
# message(STATUS "Getting SDL2_ttf from Github")
|
|
||||||
# include_dependency(SDL2_ttf https://github.com/libsdl-org/SDL_ttf.git release-2.22.0)
|
|
||||||
#else()
|
|
||||||
# message(STATUS "Using local SDL2_ttf")
|
|
||||||
#endif()
|
|
||||||
|
|
||||||
|
# Must set the path to the main.cpp, for example: scripts/main.cpp if it is inside a folder
|
||||||
add_executable(${PROJECT_NAME} scripts/main.c
|
add_executable(${PROJECT_NAME} scripts/main.c
|
||||||
scripts/array.c
|
scripts/array.c
|
||||||
scripts/vector.c
|
scripts/vector.c
|
||||||
@ -79,36 +14,12 @@ add_executable(${PROJECT_NAME} scripts/main.c
|
|||||||
scripts/texture.c
|
scripts/texture.c
|
||||||
scripts/swap.c
|
scripts/swap.c
|
||||||
scripts/upng.c
|
scripts/upng.c
|
||||||
scripts/display.c
|
scripts/display.c)
|
||||||
)
|
|
||||||
|
|
||||||
# Target include directories for non-gfx libs
|
# --- SDL2 SETUP ---
|
||||||
target_include_directories(
|
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules)
|
||||||
${PROJECT_NAME}
|
set(SDL2_PATH "SDL2/x86_64-w64-mingw32")
|
||||||
PUBLIC
|
|
||||||
${SDL2_INCLUDE_DIRS}
|
|
||||||
${SDL2_IMAGE_INCLUDE_DIRS}
|
|
||||||
# ${SDL2_TTF_INCLUDE_DIRS}
|
|
||||||
${sdl2_gfx_SOURCE_DIR} # Add SDL2_gfx headers directory
|
|
||||||
)
|
|
||||||
|
|
||||||
# link all libraries to the project
|
find_package(SDL2 REQUIRED)
|
||||||
target_link_libraries(
|
include_directories(${SDL2_INCLUDE_DIR})
|
||||||
${PROJECT_NAME}
|
target_link_libraries(${PROJECT_NAME} ${SDL2_LIBRARY} ${SDL2_IMAGE_LIBRARIES})
|
||||||
PRIVATE
|
|
||||||
SDL2::SDL2
|
|
||||||
SDL2::SDL2main
|
|
||||||
SDL2_image::SDL2_image
|
|
||||||
# SDL2_ttf::SDL2_ttf
|
|
||||||
SDL2_gfx # Link in the SDL2_gfx library we added
|
|
||||||
)
|
|
||||||
|
|
||||||
if (WIN32)
|
|
||||||
add_custom_command(
|
|
||||||
TARGET ${PROJECT_NAME} POST_BUILD
|
|
||||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "$<TARGET_FILE:SDL2::SDL2>" "$<TARGET_FILE_DIR:sdl_project>"
|
|
||||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "$<TARGET_FILE:SDL2_image::SDL2_image>" "$<TARGET_FILE_DIR:sdl_project>"
|
|
||||||
#COMMAND "${CMAKE_COMMAND}" -E copy_if_different "$<TARGET_FILE:SDL2_ttf::SDL2_ttf>" "$<TARGET_FILE_DIR:sdl_project>"
|
|
||||||
VERBATIM
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
Binary file not shown.
@ -2,10 +2,7 @@
|
|||||||
#include "display.h"
|
#include "display.h"
|
||||||
SDL_Window* window = NULL;
|
SDL_Window* window = NULL;
|
||||||
SDL_Renderer* renderer = NULL;
|
SDL_Renderer* renderer = NULL;
|
||||||
|
|
||||||
uint32_t* color_buffer = NULL;
|
uint32_t* color_buffer = NULL;
|
||||||
float* z_buffer = NULL;
|
|
||||||
|
|
||||||
SDL_Texture* color_buffer_texture = NULL;
|
SDL_Texture* color_buffer_texture = NULL;
|
||||||
int window_width = 800;
|
int window_width = 800;
|
||||||
int window_height = 600;
|
int window_height = 600;
|
||||||
@ -17,19 +14,19 @@ bool initialize_window(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set width and height of the SDL window with the max screen resolution
|
// Set width and height of the SDL window with the max screen resolution
|
||||||
/*SDL_DisplayMode display_mode;
|
SDL_DisplayMode display_mode;
|
||||||
SDL_GetCurrentDisplayMode(0, &display_mode);
|
SDL_GetCurrentDisplayMode(0, &display_mode);
|
||||||
window_width = display_mode.w;
|
window_width = display_mode.w;
|
||||||
window_height = display_mode.h;
|
window_height = display_mode.h;
|
||||||
*/
|
|
||||||
// Create a SDL Window
|
// Create a SDL Window
|
||||||
window = SDL_CreateWindow(
|
window = SDL_CreateWindow(
|
||||||
"3D Renderer",
|
NULL,
|
||||||
SDL_WINDOWPOS_CENTERED,
|
SDL_WINDOWPOS_CENTERED,
|
||||||
SDL_WINDOWPOS_CENTERED,
|
SDL_WINDOWPOS_CENTERED,
|
||||||
window_width,
|
window_width,
|
||||||
window_height,
|
window_height,
|
||||||
SDL_WINDOW_SHOWN
|
SDL_WINDOW_BORDERLESS
|
||||||
);
|
);
|
||||||
if (!window) {
|
if (!window) {
|
||||||
fprintf(stderr, "Error creating SDL window.\n");
|
fprintf(stderr, "Error creating SDL window.\n");
|
||||||
@ -107,14 +104,6 @@ void clear_color_buffer(uint32_t color) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_z_buffer() {
|
|
||||||
for (int y = 0; y < window_height; y++) {
|
|
||||||
for (int x = 0; x < window_width; x++) {
|
|
||||||
z_buffer[(window_width * y) + x] = 1.0F;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroy_window(void) {
|
void destroy_window(void) {
|
||||||
SDL_DestroyRenderer(renderer);
|
SDL_DestroyRenderer(renderer);
|
||||||
SDL_DestroyWindow(window);
|
SDL_DestroyWindow(window);
|
||||||
|
|||||||
@ -25,7 +25,6 @@ enum render_method {
|
|||||||
extern SDL_Window* window;
|
extern SDL_Window* window;
|
||||||
extern SDL_Renderer* renderer;
|
extern SDL_Renderer* renderer;
|
||||||
extern uint32_t* color_buffer;
|
extern uint32_t* color_buffer;
|
||||||
extern float* z_buffer;
|
|
||||||
extern SDL_Texture* color_buffer_texture;
|
extern SDL_Texture* color_buffer_texture;
|
||||||
extern int window_width;
|
extern int window_width;
|
||||||
extern int window_height;
|
extern int window_height;
|
||||||
@ -37,7 +36,6 @@ void draw_line(int x0, int y0, int x1, int y1, uint32_t color);
|
|||||||
void draw_rect(int x, int y, int width, int height, uint32_t color);
|
void draw_rect(int x, int y, int width, int height, uint32_t color);
|
||||||
void render_color_buffer(void);
|
void render_color_buffer(void);
|
||||||
void clear_color_buffer(uint32_t color);
|
void clear_color_buffer(uint32_t color);
|
||||||
void clear_z_buffer();
|
|
||||||
void destroy_window(void);
|
void destroy_window(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -33,9 +33,8 @@ void setup(void) {
|
|||||||
render_method = RENDER_TEXTURED_WIRE;
|
render_method = RENDER_TEXTURED_WIRE;
|
||||||
cull_method = CULL_BACKFACE;
|
cull_method = CULL_BACKFACE;
|
||||||
|
|
||||||
// Allocate the required memory in bytes to hold the color buffer and z buffer
|
// Allocate the required memory in bytes to hold the color buffer
|
||||||
color_buffer = (uint32_t*)malloc(sizeof(uint32_t) * window_width * window_height);
|
color_buffer = (uint32_t*)malloc(sizeof(uint32_t) * window_width * window_height);
|
||||||
z_buffer = (float*)malloc(sizeof(float) * window_width * window_height);
|
|
||||||
|
|
||||||
// Creating a SDL texture that is used to display the color buffer
|
// Creating a SDL texture that is used to display the color buffer
|
||||||
color_buffer_texture = SDL_CreateTexture(
|
color_buffer_texture = SDL_CreateTexture(
|
||||||
@ -208,6 +207,9 @@ void update(void) {
|
|||||||
projected_points[j].y += (window_height / 2.0);
|
projected_points[j].y += (window_height / 2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate the average depth for each face based on the vertices after transformation
|
||||||
|
float avg_depth = (transformed_vertices[0].z + transformed_vertices[1].z + transformed_vertices[2].z) / 3.0;
|
||||||
|
|
||||||
// Calculate the shade intensity based on how aliged is the normal with the flipped light direction ray
|
// Calculate the shade intensity based on how aliged is the normal with the flipped light direction ray
|
||||||
float light_intensity_factor = -vec3_dot(normal, light.direction);
|
float light_intensity_factor = -vec3_dot(normal, light.direction);
|
||||||
|
|
||||||
@ -226,11 +228,25 @@ void update(void) {
|
|||||||
{ mesh_face.c_uv.u, mesh_face.c_uv.v }
|
{ mesh_face.c_uv.u, mesh_face.c_uv.v }
|
||||||
},
|
},
|
||||||
.color = triangle_color,
|
.color = triangle_color,
|
||||||
|
.avg_depth = avg_depth
|
||||||
};
|
};
|
||||||
|
|
||||||
// Save the projected triangle in the array of triangles to render
|
// Save the projected triangle in the array of triangles to render
|
||||||
array_push(triangles_to_render, projected_triangle);
|
array_push(triangles_to_render, projected_triangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort the triangles to render by their avg_depth
|
||||||
|
int num_triangles = array_length(triangles_to_render);
|
||||||
|
for (int i = 0; i < num_triangles; i++) {
|
||||||
|
for (int j = i; j < num_triangles; j++) {
|
||||||
|
if (triangles_to_render[i].avg_depth < triangles_to_render[j].avg_depth) {
|
||||||
|
// Swap the triangles positions in the array
|
||||||
|
triangle_t temp = triangles_to_render[i];
|
||||||
|
triangles_to_render[i] = triangles_to_render[j];
|
||||||
|
triangles_to_render[j] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -249,9 +265,9 @@ void render(void) {
|
|||||||
// Draw filled triangle
|
// Draw filled triangle
|
||||||
if (render_method == RENDER_FILL_TRIANGLE || render_method == RENDER_FILL_TRIANGLE_WIRE) {
|
if (render_method == RENDER_FILL_TRIANGLE || render_method == RENDER_FILL_TRIANGLE_WIRE) {
|
||||||
draw_filled_triangle(
|
draw_filled_triangle(
|
||||||
triangle.points[0].x, triangle.points[0].y, triangle.points[0].z, triangle.points[0].w, // vertex A
|
triangle.points[0].x, triangle.points[0].y, // vertex A
|
||||||
triangle.points[1].x, triangle.points[1].y, triangle.points[1].z, triangle.points[1].w, // vertex B
|
triangle.points[1].x, triangle.points[1].y, // vertex B
|
||||||
triangle.points[2].x, triangle.points[2].y, triangle.points[2].z, triangle.points[2].w, // vertex C
|
triangle.points[2].x, triangle.points[2].y, // vertex C
|
||||||
triangle.color
|
triangle.color
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -289,9 +305,7 @@ void render(void) {
|
|||||||
|
|
||||||
render_color_buffer();
|
render_color_buffer();
|
||||||
|
|
||||||
|
|
||||||
clear_color_buffer(0xFF000000);
|
clear_color_buffer(0xFF000000);
|
||||||
clear_z_buffer();
|
|
||||||
|
|
||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
}
|
}
|
||||||
@ -301,7 +315,6 @@ void render(void) {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
void free_resources(void) {
|
void free_resources(void) {
|
||||||
free(color_buffer);
|
free(color_buffer);
|
||||||
free(z_buffer);
|
|
||||||
array_free(mesh.faces);
|
array_free(mesh.faces);
|
||||||
array_free(mesh.vertices);
|
array_free(mesh.vertices);
|
||||||
upng_free(png_texture);
|
upng_free(png_texture);
|
||||||
|
|||||||
@ -2,6 +2,122 @@
|
|||||||
#include "swap.h"
|
#include "swap.h"
|
||||||
#include "triangle.h"
|
#include "triangle.h"
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Draw a filled a triangle with a flat bottom
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// (x0,y0)
|
||||||
|
// / \
|
||||||
|
// / \
|
||||||
|
// / \
|
||||||
|
// / \
|
||||||
|
// / \
|
||||||
|
// (x1,y1)------(x2,y2)
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
void fill_flat_bottom_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t color) {
|
||||||
|
// Find the two slopes (two triangle legs)
|
||||||
|
float inv_slope_1 = (float)(x1 - x0) / (y1 - y0);
|
||||||
|
float inv_slope_2 = (float)(x2 - x0) / (y2 - y0);
|
||||||
|
|
||||||
|
// Start x_start and x_end from the top vertex (x0,y0)
|
||||||
|
float x_start = x0;
|
||||||
|
float x_end = x0;
|
||||||
|
|
||||||
|
// Loop all the scanlines from top to bottom
|
||||||
|
for (int y = y0; y <= y2; y++) {
|
||||||
|
draw_line(x_start, y, x_end, y, color);
|
||||||
|
x_start += inv_slope_1;
|
||||||
|
x_end += inv_slope_2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Draw a filled a triangle with a flat top
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// (x0,y0)------(x1,y1)
|
||||||
|
// \ /
|
||||||
|
// \ /
|
||||||
|
// \ /
|
||||||
|
// \ /
|
||||||
|
// \ /
|
||||||
|
// (x2,y2)
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
void fill_flat_top_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t color) {
|
||||||
|
// Find the two slopes (two triangle legs)
|
||||||
|
float inv_slope_1 = (float)(x2 - x0) / (y2 - y0);
|
||||||
|
float inv_slope_2 = (float)(x2 - x1) / (y2 - y1);
|
||||||
|
|
||||||
|
// Start x_start and x_end from the bottom vertex (x2,y2)
|
||||||
|
float x_start = x2;
|
||||||
|
float x_end = x2;
|
||||||
|
|
||||||
|
// Loop all the scanlines from bottom to top
|
||||||
|
for (int y = y2; y >= y0; y--) {
|
||||||
|
draw_line(x_start, y, x_end, y, color);
|
||||||
|
x_start -= inv_slope_1;
|
||||||
|
x_end -= inv_slope_2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Draw a filled triangle with the flat-top/flat-bottom method
|
||||||
|
// We split the original triangle in two, half flat-bottom and half flat-top
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// (x0,y0)
|
||||||
|
// / \
|
||||||
|
// / \
|
||||||
|
// / \
|
||||||
|
// / \
|
||||||
|
// / \
|
||||||
|
// (x1,y1)------(Mx,My)
|
||||||
|
// \_ \
|
||||||
|
// \_ \
|
||||||
|
// \_ \
|
||||||
|
// \_ \
|
||||||
|
// \ \
|
||||||
|
// \_ \
|
||||||
|
// \_\
|
||||||
|
// \
|
||||||
|
// (x2,y2)
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
void draw_filled_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t color) {
|
||||||
|
// We need to sort the vertices by y-coordinate ascending (y0 < y1 < y2)
|
||||||
|
if (y0 > y1) {
|
||||||
|
int_swap(&y0, &y1);
|
||||||
|
int_swap(&x0, &x1);
|
||||||
|
}
|
||||||
|
if (y1 > y2) {
|
||||||
|
int_swap(&y1, &y2);
|
||||||
|
int_swap(&x1, &x2);
|
||||||
|
}
|
||||||
|
if (y0 > y1) {
|
||||||
|
int_swap(&y0, &y1);
|
||||||
|
int_swap(&x0, &x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y1 == y2) {
|
||||||
|
// Draw flat-bottom triangle
|
||||||
|
fill_flat_bottom_triangle(x0, y0, x1, y1, x2, y2, color);
|
||||||
|
} else if (y0 == y1) {
|
||||||
|
// Draw flat-top triangle
|
||||||
|
fill_flat_top_triangle(x0, y0, x1, y1, x2, y2, color);
|
||||||
|
} else {
|
||||||
|
// Calculate the new vertex (Mx,My) using triangle similarity
|
||||||
|
int My = y1;
|
||||||
|
int Mx = (((x2 - x0) * (y1 - y0)) / (y2 - y0)) + x0;
|
||||||
|
|
||||||
|
// Draw flat-bottom triangle
|
||||||
|
fill_flat_bottom_triangle(x0, y0, x1, y1, Mx, My, color);
|
||||||
|
|
||||||
|
// Draw flat-top triangle
|
||||||
|
fill_flat_top_triangle(x1, y1, Mx, My, x2, y2, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Draw a triangle using three raw line calls
|
// Draw a triangle using three raw line calls
|
||||||
@ -92,59 +208,7 @@ void draw_texel(
|
|||||||
int tex_y = abs((int)(interpolated_v * texture_height)) % texture_height;
|
int tex_y = abs((int)(interpolated_v * texture_height)) % texture_height;
|
||||||
//tex_x = SDL_clamp(tex_x, 0, texture_width);
|
//tex_x = SDL_clamp(tex_x, 0, texture_width);
|
||||||
//tex_y = SDL_clamp(tex_y, 0, texture_height);
|
//tex_y = SDL_clamp(tex_y, 0, texture_height);
|
||||||
|
draw_pixel(x, y, texture[(texture_width * tex_y) + tex_x]);
|
||||||
int z_pos = (window_width * y) + x;
|
|
||||||
|
|
||||||
// Adjust 1/w so the pixels that are closer to the camera have smaller values
|
|
||||||
interpolated_reciprocal_w = 1.0 - interpolated_reciprocal_w;
|
|
||||||
|
|
||||||
// only draw pixel if depth value is less than one previously stored in z-buffer
|
|
||||||
if (interpolated_reciprocal_w < z_buffer[z_pos]) {
|
|
||||||
draw_pixel(x, y, texture[(texture_width * tex_y) + tex_x]);
|
|
||||||
|
|
||||||
// update z-buffer value with the 1/w of this current pixel
|
|
||||||
z_buffer[z_pos] = interpolated_reciprocal_w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw_triangle_pixel(
|
|
||||||
int x, int y, uint32_t color,
|
|
||||||
vec4_t point_a, vec4_t point_b, vec4_t point_c
|
|
||||||
) {
|
|
||||||
vec2_t p = { x, y };
|
|
||||||
vec2_t a = vec2_from_vec4(point_a);
|
|
||||||
vec2_t b = vec2_from_vec4(point_b);
|
|
||||||
vec2_t c = vec2_from_vec4(point_c);
|
|
||||||
|
|
||||||
// Calculate the barycentric coordinates of our point 'p' inside the triangle
|
|
||||||
vec3_t weights = barycentric_weights(a, b, c, p);
|
|
||||||
|
|
||||||
float alpha = weights.x;
|
|
||||||
float beta = weights.y;
|
|
||||||
float gamma = weights.z;
|
|
||||||
|
|
||||||
// Variables to store the interpolated values of U, V, and also 1/w for the current pixel
|
|
||||||
float interpolated_reciprocal_w;
|
|
||||||
|
|
||||||
// Also interpolate the value of 1/w for the current pixel
|
|
||||||
interpolated_reciprocal_w = (1 / point_a.w) * alpha + (1 / point_b.w) * beta + (1 / point_c.w) * gamma;
|
|
||||||
|
|
||||||
// Now we can divide back both interpolated values by 1/w
|
|
||||||
//tex_x = SDL_clamp(tex_x, 0, texture_width);
|
|
||||||
//tex_y = SDL_clamp(tex_y, 0, texture_height);
|
|
||||||
|
|
||||||
int z_pos = (window_width * y) + x;
|
|
||||||
|
|
||||||
// Adjust 1/w so the pixels that are closer to the camera have smaller values
|
|
||||||
interpolated_reciprocal_w = 1.0 - interpolated_reciprocal_w;
|
|
||||||
|
|
||||||
// only draw pixel if depth value is less than one previously stored in z-buffer
|
|
||||||
if (interpolated_reciprocal_w < z_buffer[z_pos]) {
|
|
||||||
draw_pixel(x, y, color);
|
|
||||||
|
|
||||||
// update z-buffer value with the 1/w of this current pixel
|
|
||||||
z_buffer[z_pos] = interpolated_reciprocal_w;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -262,86 +326,3 @@ void draw_textured_triangle(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_filled_triangle(
|
|
||||||
int x0, int y0, float z0, float w0,
|
|
||||||
int x1, int y1, float z1, float w1,
|
|
||||||
int x2, int y2, float z2, float w2,
|
|
||||||
uint32_t color
|
|
||||||
) {
|
|
||||||
// We need to sort the vertices by y-coordinate ascending (y0 < y1 < y2)
|
|
||||||
if (y0 > y1) {
|
|
||||||
int_swap(&y0, &y1);
|
|
||||||
int_swap(&x0, &x1);
|
|
||||||
float_swap(&z0, &z1);
|
|
||||||
float_swap(&w0, &w1);
|
|
||||||
}
|
|
||||||
if (y1 > y2) {
|
|
||||||
int_swap(&y1, &y2);
|
|
||||||
int_swap(&x1, &x2);
|
|
||||||
float_swap(&z1, &z2);
|
|
||||||
float_swap(&w1, &w2);
|
|
||||||
}
|
|
||||||
if (y0 > y1) {
|
|
||||||
int_swap(&y0, &y1);
|
|
||||||
int_swap(&x0, &x1);
|
|
||||||
float_swap(&z0, &z1);
|
|
||||||
float_swap(&w0, &w1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Create vector points and texture coords after we sort the vertices
|
|
||||||
vec4_t point_a = { x0, y0, z0, w0 };
|
|
||||||
vec4_t point_b = { x1, y1, z1, w1 };
|
|
||||||
vec4_t point_c = { x2, y2, z2, w2 };
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
|
||||||
// Render the upper part of the triangle (flat-bottom)
|
|
||||||
///////////////////////////////////////////////////////
|
|
||||||
float inv_slope_1 = 0;
|
|
||||||
float inv_slope_2 = 0;
|
|
||||||
|
|
||||||
if (y1 - y0 != 0) inv_slope_1 = (float)(x1 - x0) / abs(y1 - y0);
|
|
||||||
if (y2 - y0 != 0) inv_slope_2 = (float)(x2 - x0) / abs(y2 - y0);
|
|
||||||
|
|
||||||
if (y1 - y0 != 0) {
|
|
||||||
for (int y = y0; y <= y1; y++) {
|
|
||||||
int x_start = x1 + (y - y1) * inv_slope_1;
|
|
||||||
int x_end = x0 + (y - y0) * inv_slope_2;
|
|
||||||
|
|
||||||
if (x_end < x_start) {
|
|
||||||
int_swap(&x_start, &x_end); // swap if x_start is to the right of x_end
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int x = x_start; x < x_end; x++) {
|
|
||||||
// Draw our pixel with the color that comes from the texture
|
|
||||||
draw_triangle_pixel(x, y, color, point_a, point_b, point_c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
|
||||||
// Render the bottom part of the triangle (flat-top)
|
|
||||||
///////////////////////////////////////////////////////
|
|
||||||
inv_slope_1 = 0;
|
|
||||||
inv_slope_2 = 0;
|
|
||||||
|
|
||||||
if (y2 - y1 != 0) inv_slope_1 = (float)(x2 - x1) / abs(y2 - y1);
|
|
||||||
if (y2 - y0 != 0) inv_slope_2 = (float)(x2 - x0) / abs(y2 - y0);
|
|
||||||
|
|
||||||
if (y2 - y1 != 0) {
|
|
||||||
for (int y = y1; y <= y2; y++) {
|
|
||||||
int x_start = x1 + (y - y1) * inv_slope_1;
|
|
||||||
int x_end = x0 + (y - y0) * inv_slope_2;
|
|
||||||
|
|
||||||
if (x_end < x_start) {
|
|
||||||
int_swap(&x_start, &x_end); // swap if x_start is to the right of x_end
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int x = x_start; x < x_end; x++) {
|
|
||||||
// Draw our pixel with the color that comes from the texture
|
|
||||||
draw_triangle_pixel(x, y, color, point_a, point_b, point_c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -23,12 +23,8 @@ typedef struct {
|
|||||||
} triangle_t;
|
} triangle_t;
|
||||||
|
|
||||||
void draw_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t color);
|
void draw_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t color);
|
||||||
void draw_filled_triangle(
|
void draw_filled_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t color);
|
||||||
int x0, int y0, float z0, float w0,
|
|
||||||
int x1, int y1, float z1, float w1,
|
|
||||||
int x2, int y2, float z2, float w2,
|
|
||||||
uint32_t color
|
|
||||||
);
|
|
||||||
void draw_textured_triangle(
|
void draw_textured_triangle(
|
||||||
int x0, int y0, float z0, float w0, float u0, float v0,
|
int x0, int y0, float z0, float w0, float u0, float v0,
|
||||||
int x1, int y1, float z1, float w1, float u1, float v1,
|
int x1, int y1, float z1, float w1, float u1, float v1,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user