summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-06-12 00:16:51 +1000
committeromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-06-12 00:16:51 +1000
commit26fb1fcafa552c600a70b2680c868f7355b138e4 (patch)
tree2fb77c8b14a5610584a316e57fd8db2795847a0f
parent76216f91aee936bc57d7e1a1b2c2b63a03ce976a (diff)
wip: uvsphere mesh gen and pbr shader first pass
-rw-r--r--assets/shaders/pbr_params.frag85
-rw-r--r--examples/primitives/ex_primitives.c53
-rw-r--r--src/maths/primitives.c64
-rw-r--r--src/maths/primitives.h2
-rw-r--r--src/renderer/render_types.h12
-rw-r--r--src/resources/gltf.c2
-rw-r--r--xmake.lua7
7 files changed, 217 insertions, 8 deletions
diff --git a/assets/shaders/pbr_params.frag b/assets/shaders/pbr_params.frag
new file mode 100644
index 0000000..06e0f7e
--- /dev/null
+++ b/assets/shaders/pbr_params.frag
@@ -0,0 +1,85 @@
+#version 410
+
+out vec4 FragColor;
+
+in vec3 WorldPos;
+in vec3 Normal;
+in vec2 TexCoords;
+
+struct PointLight {
+ vec3 position;
+ vec3 color;
+};
+
+// --- Uniforms
+uniform vec3 viewPos;
+// Lights data
+#define NUM_POINT_LIGHTS 4
+uniform PointLight pointLights[NUM_POINT_LIGHTS];
+// Material properties
+uniform vec3 albedo;
+uniform float metallic;
+uniform float roughness;
+uniform float ao;
+
+// Forward declarations
+vec3 fresnelSchlick(float cosTheta, vec3 F0);
+float DistributionGGX(vec3 N, vec3 H, float roughness);
+float GeometrySchlickGGX(float NdotV, float roughness);
+float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness);
+
+void main() {
+ vec3 norm = normalize(Normal);
+ vec3 viewDir = normalize(viewPos - WorldPos);
+
+ vec3 radiance = vec3(0.0); // denoted L in the radiance equation
+ for (int i = 0; i < 4; i++) {
+ vec3 lightVec = normalize(pointLights[i].position - WorldPos);
+ vec3 halfway = normalize(Normal + lightVec);
+ float distance = length(pointLights[i].position - WorldPos);
+ float attenuation = 1.0 / (distance * distance);
+ vec3 radiance = pointLights[i].color * attenuation;
+
+ vec3 F0 = vec3(0.04);
+ F0 = mix(F0, albedo, metallic);
+ vec3 F = fresnelSchlick(max(dot(halfway, lightVec), 0.0), F0);
+ }
+}
+
+/* The below are from https://learnopengl.com/PBR/Lighting */
+
+vec3 fresnelSchlick(float cosTheta, vec3 F0) {
+ return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
+}
+float DistributionGGX(vec3 N, vec3 H, float roughness) {
+ float a = roughness*roughness;
+ float a2 = a*a;
+ float NdotH = max(dot(N, H), 0.0);
+ float NdotH2 = NdotH*NdotH;
+
+ float num = a2;
+ float denom = (NdotH2 * (a2 - 1.0) + 1.0);
+ denom = PI * denom * denom;
+
+ return num / denom;
+}
+
+float GeometrySchlickGGX(float NdotV, float roughness)
+{
+ float r = (roughness + 1.0);
+ float k = (r*r) / 8.0;
+
+ float num = NdotV;
+ float denom = NdotV * (1.0 - k) + k;
+
+ return num / denom;
+}
+float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
+{
+ float NdotV = max(dot(N, V), 0.0);
+ float NdotL = max(dot(N, L), 0.0);
+ float ggx2 = GeometrySchlickGGX(NdotV, roughness);
+ float ggx1 = GeometrySchlickGGX(NdotL, roughness);
+
+ return ggx1 * ggx2;
+} \ No newline at end of file
diff --git a/examples/primitives/ex_primitives.c b/examples/primitives/ex_primitives.c
new file mode 100644
index 0000000..c208734
--- /dev/null
+++ b/examples/primitives/ex_primitives.c
@@ -0,0 +1,53 @@
+#include <glfw3.h>
+
+#include "buf.h"
+#include "camera.h"
+#include "core.h"
+#include "file.h"
+#include "log.h"
+#include "maths.h"
+#include "maths_types.h"
+#include "mem.h"
+#include "primitives.h"
+#include "ral.h"
+#include "ral_types.h"
+#include "render.h"
+#include "render_types.h"
+
+extern core g_core;
+
+int main() {
+ core_bringup();
+ arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024);
+
+ vec3 camera_pos = vec3(2., 2., 2.);
+ vec3 camera_front = vec3_normalise(vec3_negate(camera_pos));
+ camera cam = camera_create(camera_pos, camera_front, VEC3_Y, deg_to_rad(45.0));
+
+ // Geometry
+ // geo_create_cuboid(f32x3(1, 1, 1));
+ geometry_data sphere_data = geo_create_uvsphere(2.0, 8, 8);
+ mesh sphere = mesh_create(&sphere_data, false);
+
+ // Texture
+ texture_data tex_data = texture_data_load("assets/textures/texture.jpg", false);
+ texture_handle texture = texture_data_upload(tex_data, true);
+
+ static f32 theta = 0.0;
+
+ // Main loop
+ while (!should_exit(&g_core)) {
+ input_update(&g_core.input);
+
+ render_frame_begin(&g_core.renderer);
+
+ mat4 model = mat4_ident();
+ draw_mesh(&sphere, &model, &cam);
+
+ render_frame_end(&g_core.renderer);
+ }
+
+ renderer_shutdown(&g_core.renderer);
+
+ return 0;
+}
diff --git a/src/maths/primitives.c b/src/maths/primitives.c
index c0af140..3931b93 100644
--- a/src/maths/primitives.c
+++ b/src/maths/primitives.c
@@ -112,7 +112,7 @@ geometry_data geo_create_cuboid(f32x3 extents) {
.vertices = vertices,
.has_indices = true,
.indices = indices, // FIXME: make darray methods that return stack allocated struct
- .colour = vec3(0, 0, 0),
+ .colour = (rgba){ 0, 0, 0, 1 }
};
return geo;
@@ -133,6 +133,64 @@ geometry_data geo_create_cuboid(f32x3 extents) {
// --- Spheres
-geometry_data geo_create_uvsphere(f32 radius, f32 north_south_lines, f32 east_west_lines) {
- // TODO
+vec3 spherical_to_cartesian_coords(f32 rho, f32 theta, f32 phi) {
+ f32 x = rho * sin(phi) * cos(theta);
+ f32 y = rho * sin(phi) * sin(theta);
+ f32 z = rho * cos(phi);
+ return vec3(x, y, z);
+}
+
+geometry_data geo_create_uvsphere(f32 radius, u32 north_south_lines, u32 east_west_lines) {
+ assert(east_west_lines >= 3); // sphere will be degenerate and look gacked without at least 3
+ assert(north_south_lines >= 3);
+
+ vertex_darray* vertices = vertex_darray_new(2 + (east_west_lines - 1) * north_south_lines);
+
+ // Create a UV sphere with spherical coordinates
+ // a point P on the unit sphere can be represented P(r, theta, phi)
+ // for each vertex we must convert that to a cartesian R3 coordinate
+
+ // Top point
+ vertex top = { .static_3d = { .position = vec3(0, 0, radius),
+ .normal = vec3(0, 0, radius),
+ .tex_coords = vec2(0, 0) } };
+
+ // parallels
+ for (u32 i = 0; i < (east_west_lines - 1); i++) {
+ // phi should range from 0 to pi
+ f32 phi = PI * ((i + 1) / east_west_lines);
+
+ // meridians
+ for (u32 j = 0; j < east_west_lines; j++) {
+ // theta should range from 0 to 2PI
+ f32 theta = TAU * (j / north_south_lines);
+ vec3 position = spherical_to_cartesian_coords(radius, theta, phi);
+ f32 d = vec3_len(position);
+ assert(d == radius); // all points on the sphere should be 'radius' away from the origin
+ vertex v = { .static_3d = {
+ .position = position,
+ .normal = position, // normal vector on sphere is same as position
+ .tex_coords = vec2(0, 0) // TODO
+ } };
+ vertex_darray_push(vertices, v);
+ }
+ }
+
+ // Bottom point
+ vertex bot = { .static_3d = { .position = vec3(0, 0, -radius),
+ .normal = vec3(0, 0, -radius),
+ .tex_coords = vec2(0, 0) } };
+
+ // TODO: generate indices for for each flat quad on the UV sphere and triangles
+ // where they meet the north and south poles
+ u32_darray* indices = u32_darray_new(1);
+
+ geometry_data geo = {
+ .format = VERTEX_STATIC_3D,
+ .vertices = vertices,
+ .has_indices = true,
+ .indices = indices,
+ .colour = RED_800,
+ };
+ return geo;
}
diff --git a/src/maths/primitives.h b/src/maths/primitives.h
index 3e0cc5f..be2c6ff 100644
--- a/src/maths/primitives.h
+++ b/src/maths/primitives.h
@@ -9,5 +9,5 @@
geometry_data geo_create_plane(f32x2 extents);
geometry_data geo_create_cuboid(f32x3 extents);
geometry_data geo_create_cylinder(f32 radius, f32 height, u32 resolution);
-geometry_data geo_create_uvsphere(f32 radius, f32 north_south_lines, f32 east_west_lines);
+geometry_data geo_create_uvsphere(f32 radius, u32 north_south_lines, u32 east_west_lines);
geometry_data geo_create_icosphere(f32 radius, f32 n_subdivisions); \ No newline at end of file
diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h
index b8ed512..1485ae4 100644
--- a/src/renderer/render_types.h
+++ b/src/renderer/render_types.h
@@ -13,6 +13,7 @@
#include "defines.h"
#include "ral.h"
#include "ral_types.h"
+#include "colours.h"
#if defined(CEL_PLATFORM_WINDOWS)
// #include "backend_dx11.h"
#endif
@@ -31,7 +32,7 @@ typedef struct geometry_data {
vertex_darray* vertices; // TODO: make it not a pointer
bool has_indices;
u32_darray* indices;
- vec3 colour; /** Optional: set vertex colours */
+ rgba colour; /** Optional: set vertex colours */
} geometry_data;
// 'Upload' a geometry_data (to GPU) -> get back a mesh
@@ -65,9 +66,10 @@ typedef struct texture_data {
typedef enum material_kind {
MAT_BLINN_PHONG,
MAT_PBR,
+ MAT_PBR_PARAMS, // uses float values to represent a surface uniformly
MAT_COUNT
} material_kind;
-static const char* material_kind_names[] = { "Blinn Phong", "PBR", "Count (This should be an error)"};
+static const char* material_kind_names[] = { "Blinn Phong", "PBR (Textures)", "PBR (Params)", "Count (This should be an error)"};
typedef struct blinn_phong_material {
char name[256];
@@ -85,7 +87,10 @@ typedef struct blinn_phong_material {
// typedef blinn_phong_material material;
typedef struct pbr_parameters {
-
+ vec3 albedo;
+ f32 metallic;
+ f32 roughness;
+ f32 ao;
} pbr_parameters;
typedef struct pbr_material {
@@ -101,6 +106,7 @@ typedef struct material {
material_kind kind;
union {
blinn_phong_material blinn_phong;
+ pbr_parameters pbr_params;
pbr_material pbr;
} mat_data;
char* name;
diff --git a/src/resources/gltf.c b/src/resources/gltf.c
index dcb3d96..46ad4f3 100644
--- a/src/resources/gltf.c
+++ b/src/resources/gltf.c
@@ -380,7 +380,7 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel
geometry_data *geometry = malloc(sizeof(geometry_data));
geometry->format = VERTEX_STATIC_3D;
- geometry->colour = vec3(1, 1, 1);
+ geometry->colour = (rgba){ 1, 1, 1, 1 };
geometry->vertices = geo_vertices;
geometry->indices = geo_indices;
geometry->has_indices = has_indices;
diff --git a/xmake.lua b/xmake.lua
index 598b7a3..55af4f2 100644
--- a/xmake.lua
+++ b/xmake.lua
@@ -188,6 +188,13 @@ target("cube")
add_files("examples/cube/ex_cube.c")
set_rundir("$(projectdir)")
+target("primitives")
+ set_kind("binary")
+ set_group("examples")
+ add_deps("core_static")
+ add_files("examples/primitives/ex_primitives.c")
+ set_rundir("$(projectdir)")
+
-- target("std")
-- set_kind("binary")
-- set_group("examples")