Basic alpha blending works but I have no z ordering yet.

This commit is contained in:
Zed A. Shaw 2026-08-29 16:08:33 -04:00
parent 128f522089
commit 11b7f4a3ed
14 changed files with 272 additions and 30 deletions

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

View file

@ -1,12 +1,12 @@
{
"scene": {
"shader": {
"vertex_path": "shaders/18-vert.glsl",
"frag_path": "shaders/18-frag.glsl"
"vertex_path": "shaders/19-vert.glsl",
"frag_path": "shaders/19-frag.glsl"
},
"light_shader": {
"vertex_path": "shaders/18-vert.glsl",
"frag_path": "shaders/18-lightsource.frag.glsl"
"vertex_path": "shaders/19-vert.glsl",
"frag_path": "shaders/19-lightsource.frag.glsl"
},
"materials": {
"default": {
@ -30,12 +30,29 @@
"metal_floor": {
"directory": "assets",
"model_path": "metal_floor.glb"
},
"grass": {
"directory": "assets",
"model_path": "grass.glb"
}
},
"things": [
{"model": "marble_cube", "position": [-1.0, 0.0, -1.0], "material": "default"},
{"model": "marble_cube", "position": [2.0, 0.0, 0.0], "material": "default"},
{"model": "metal_floor", "position": [0.0, 0.0, 0.0], "material": "shiny"}
{"model": "marble_cube", "position": [-1.0, 0.0, -1.0],
"rotation": {"angle": 0.0, "axes": [1.0, 1.0, 1.0]},
"scale": 1.0,
"material": "default"},
{"model": "marble_cube", "position": [2.0, 0.0, 0.0],
"rotation": {"angle": 0.0, "axes": [1.0, 1.0, 1.0]},
"scale": 1.0,
"material": "default"},
{"model": "metal_floor", "position": [0.0, 0.0, 0.0],
"rotation": {"angle": 0.0, "axes": [1.0, 1.0, 1.0]},
"scale": 1.0,
"material": "shiny"},
{"model": "grass", "position": [0.5, 0.13, 0.0],
"rotation": {"angle": 90.0, "axes": [1.0,0.0,0.0]},
"scale": 1.0,
"material": "default"}
],
"camera": {
"position": [0.0, 0.1, 3.0],

View file

@ -0,0 +1,168 @@
#version 330 core
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
out vec4 FragColor;
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
uniform vec3 viewPos;
uniform Material material;
struct DirLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct PointLight {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
struct SpotLight {
vec3 direction;
vec3 position;
vec3 diffuse;
vec3 specular;
vec3 ambient;
float constant;
float linear;
float quadratic;
float cut_off;
float outer_cut_off;
};
#define MAX_LIGHTS 4
uniform int pointLightCount = 0;
uniform PointLight pointLights[MAX_LIGHTS];
uniform int dirLightCount = 0;
uniform DirLight dirLights[MAX_LIGHTS];
uniform int spotLightCount = 0;
uniform SpotLight spotLights[MAX_LIGHTS];
float near = 0.1;
float far = 100.0;
vec4 CalcDirLight(vec4 mat_tex, vec4 spec_tex, DirLight light, vec3 normal, vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec4 ambient = vec4(light.ambient, 1.0) * mat_tex;
vec4 diffuse = vec4(light.diffuse, 1.0) * diff * mat_tex;
vec4 specular = vec4(light.specular, 1.0) * spec * spec_tex;
return ambient + diffuse + specular;
}
vec4 CalcPointLight(vec4 mat_tex, vec4 spec_tex, PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
vec4 ambient = vec4(light.ambient, 1.0) * mat_tex;
vec4 diffuse = vec4(light.diffuse, 1.0) * diff * mat_tex;
vec4 specular = vec4(light.specular, 1.0) * spec * spec_tex;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return ambient + diffuse + specular;
}
vec4 CalcSpotLight(vec4 mat_tex, vec4 spec_tex, SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
vec4 ambient = vec4(light.ambient, 1.0) * mat_tex;
vec4 diffuse = vec4(light.diffuse, 1.0) * diff * mat_tex;
vec4 specular = vec4(light.specular, 1.0) * spec * spec_tex;
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = light.cut_off - light.outer_cut_off;
float intensity = clamp((theta - light.outer_cut_off) / epsilon, 0.0, 1.0);
diffuse *= intensity;
specular *= intensity;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return ambient + diffuse + specular;
}
float LinearizeDepth(float depth)
{
float ndc = depth * 2.0 - 1.0;
return (2.0 * near * far) / (far + near - ndc * (far - near));
}
void main()
{
vec4 mat_tex = texture(material.diffuse, TexCoords);
vec4 spec_tex = texture(material.specular, TexCoords);
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
// kick it off with the first dirlight
vec4 result = CalcDirLight(mat_tex, spec_tex, dirLights[0], norm, viewDir);
// then augment with more (off by one)
for(int i = 1; i < dirLightCount; i++) {
result += CalcDirLight(mat_tex, spec_tex, dirLights[i], norm, viewDir);
}
for(int i = 0; i < pointLightCount; i++) {
result += CalcPointLight(mat_tex, spec_tex, pointLights[i], norm, FragPos, viewDir);
}
for(int i = 0; i < spotLightCount; i++) {
result += CalcSpotLight(mat_tex, spec_tex, spotLights[i], norm, FragPos, viewDir);
}
FragColor = result;
}

View file

@ -0,0 +1,9 @@
#version 330 core
out vec4 FragColor;
uniform vec3 diffuse;
void main()
{
FragColor = vec4(diffuse, 1.0); // set all 4 vector values to 1.0
}

View file

@ -0,0 +1,20 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0f);
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoords = aTexCoords;
}

View file

@ -75,14 +75,22 @@ namespace components {
ENROLL_COMPONENT(Model, directory, model_path);
using Position = glm::vec3;
struct Rotation {
float angle = 0;
glm::vec3 axes{1.0f, 0.0f, 0.0f};
};
ENROLL_COMPONENT(Rotation, angle, axes);
struct Thing {
std::string model;
Position position;
std::string material;
Position position;
Rotation rotation;
float scale;
};
ENROLL_COMPONENT(Thing, model, position, material);
ENROLL_COMPONENT(Thing, model, material, position, rotation, scale);
struct Shader {
std::string vertex_path;

View file

@ -66,24 +66,33 @@ void process_input(GLFWwindow *window, Scene& scene) {
}
if(glfwGetKey(window, GLFW_KEY_M) == GLFW_PRESS) {
scene.spawn("marble_cube", scene.camera.position);
components::Rotation rotation{90.0f, {1.0f, 0.0f, 0.0f}};
scene.spawn("grass", scene.camera.position, rotation);
}
if(glfwGetKey(window, GLFW_KEY_L) == GLFW_PRESS) {
for(auto& light : scene.light.directional) {
light.adjust(-0.01f);
}
scene.shader.apply_lighting(scene.light);
}
if(glfwGetKey(window, GLFW_KEY_P) == GLFW_PRESS) {
for(auto& light : scene.light.directional) {
light.adjust(0.01f);
}
scene.shader.apply_lighting(scene.light);
}
}
Scene setup() {
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthFunc(GL_LESS);
components::Scene config = utils::load_scene_config("config.json");

View file

@ -31,6 +31,8 @@ unsigned int image_to_texture(unsigned char *data, int width, int height, int nr
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

View file

@ -10,17 +10,18 @@ void Scene::update() {
camera.update(deltaTime);
}
void Scene::draw_model(Shader& with_shader, Model& scene_model, Material& material, glm::vec3& position, float scale)
void Scene::draw_thing(Shader& with_shader, Thing& thing)
{
with_shader.apply_material(material);
with_shader.apply_material(thing.material);
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, position);
model = glm::scale(model, glm::vec3(scale, scale, scale));
model = glm::translate(model, thing.position);
model = glm::rotate(model, glm::radians(thing.rotation.angle), thing.rotation.axes);
model = glm::scale(model, glm::vec3(thing.scale));
with_shader.setMat4("model", model);
scene_model.draw(with_shader);
thing.model.draw(with_shader);
}
void Scene::render(GLFWwindow* window) {
@ -47,7 +48,7 @@ void Scene::render(GLFWwindow* window) {
}
for(auto& thing : things) {
draw_model(shader, thing.model, thing.material, thing.position);
draw_thing(shader, thing);
}
}
@ -55,13 +56,15 @@ void Scene::cleanup() {
shader.cleanup();
}
void Scene::spawn(const std::string& name, components::Position& position) {
void Scene::spawn(const std::string& name, components::Position& position, components::Rotation& rotation) {
if(models.contains(name)) {
things.emplace_back(
name,
models.at(name),
materials.at("default"),
position,
materials.at("default"));
rotation,
1.0f);
} else {
dbc::log($F("No model named: {}", name));
}

View file

@ -16,8 +16,10 @@
struct Thing {
std::string name;
Model& model;
components::Position position;
Material& material;
components::Position position;
components::Rotation rotation;
float scale;
};
struct Scene {
@ -54,8 +56,10 @@ struct Scene {
things.emplace_back(
thing.model,
models.at(thing.model),
materials.at(thing.material),
thing.position,
materials.at(thing.material));
thing.rotation,
thing.scale);
}
shader.use();
@ -63,8 +67,8 @@ struct Scene {
}
void update();
void draw_model(Shader& with_shader, Model& scene_model, Material& material, glm::vec3& position, float scale=1.0f);
void draw_thing(Shader& with_shader, Thing& thing);
void render(GLFWwindow* window);
void cleanup();
void spawn(const std::string& name, components::Position& position);
void spawn(const std::string& name, components::Position& position, components::Rotation& rotation);
};

View file

@ -62,10 +62,11 @@
"directory": "assets",
"model_path": "create.obj"
},
"thing_test": {
"model": "crate",
"position": [0.0, 0.0, 0.0],
"material": "crate"
"thing_test":
{"model": "grass", "position": [2.5, 0.0, 0.0],
"rotation": {"angle": 90.0, "axes": [0.0,1.0,0.0,0.0]},
"scale": 1.0,
"material": "default"
},
"shader_test": {
"vertex_path": "shaders/16-vert.glsl",