diff --git a/docs/SimplexTriangleEditor.md b/docs/SimplexTriangleEditor.md new file mode 100644 index 00000000..5ad6488e --- /dev/null +++ b/docs/SimplexTriangleEditor.md @@ -0,0 +1,57 @@ +# SimplexTriangleEditor + +The `SimplexTriangleEditor` is a Jetpack Compose UI component that provides an interactive equilateral triangle for selecting barycentric weights. It is particularly useful for blending three different properties, such as colors, textures, or shader parameters. + +## Features + +- **Visual Interaction**: Drag or tap anywhere inside the triangle to move the selector handle. +- **Barycentric Mapping**: Automatically calculates three normalized weights ($a + b + c = 1.0$) based on the handle's position. +- **Responsive Layout**: Dynamically adjusts its geometry based on the available canvas size. +- **Visual Cues**: Colors the vertices (Red, Green, Blue) to represent the weight influence of each corner. + +## Usage + +### Data Model + +The widget uses a simple data class to hold the weights: + +```kotlin +data class SimplexWeights(val a: Float, val b: Float, val c: Float) +``` + +### Basic Example + +```kotlin +@Composable +fun WeightSelectionScreen() { + var weights by remember { + mutableStateOf(SimplexWeights(0.333f, 0.333f, 0.334f)) + } + + SimplexTriangleEditor( + modifier = Modifier.size(300.dp), + initialWeights = weights, + onWeightsChanged = { newWeights -> + weights = newWeights + // Update your logic or native shaders here + println("Weights: A=${newWeights.a}, B=${newWeights.b}, C=${newWeights.c}") + } + ) +} +``` + +## Parameters + +| Parameter | Type | Description | +| :--- | :--- | :--- | +| `modifier` | `Modifier` | Standard Compose modifier for layout and sizing. | +| `initialWeights` | `SimplexWeights` | The starting position of the selector handle. Defaults to center. | +| `onWeightsChanged` | `(SimplexWeights) -> Unit` | Callback triggered whenever the handle is moved or tapped. | + +## Implementation Details + +The widget implements **Inverse Kinematics** to map 2D pixel offsets from the screen into normalized barycentric coordinates. It ensures that even if a user taps slightly outside the triangle bounds, the resulting weights are clamped and re-normalized to maintain a valid state for rendering engines. + +--- + +*Part of the LearnGLES tutorial series.* diff --git a/tutorial/src/main/assets/shaders/bloom/7.bloom.frag b/tutorial/src/main/assets/shaders/bloom/bloom.frag similarity index 100% rename from tutorial/src/main/assets/shaders/bloom/7.bloom.frag rename to tutorial/src/main/assets/shaders/bloom/bloom.frag diff --git a/tutorial/src/main/assets/shaders/bloom/7.bloom.vert b/tutorial/src/main/assets/shaders/bloom/bloom.vert similarity index 100% rename from tutorial/src/main/assets/shaders/bloom/7.bloom.vert rename to tutorial/src/main/assets/shaders/bloom/bloom.vert diff --git a/tutorial/src/main/assets/shaders/bloom/7.bloom_final.frag b/tutorial/src/main/assets/shaders/bloom/bloom_final.frag similarity index 100% rename from tutorial/src/main/assets/shaders/bloom/7.bloom_final.frag rename to tutorial/src/main/assets/shaders/bloom/bloom_final.frag diff --git a/tutorial/src/main/assets/shaders/bloom/7.bloom_final.vert b/tutorial/src/main/assets/shaders/bloom/bloom_final.vert similarity index 100% rename from tutorial/src/main/assets/shaders/bloom/7.bloom_final.vert rename to tutorial/src/main/assets/shaders/bloom/bloom_final.vert diff --git a/tutorial/src/main/assets/shaders/bloom/7.blur.frag b/tutorial/src/main/assets/shaders/bloom/blur.frag similarity index 81% rename from tutorial/src/main/assets/shaders/bloom/7.blur.frag rename to tutorial/src/main/assets/shaders/bloom/blur.frag index 25eb48a9..f085d3d2 100644 --- a/tutorial/src/main/assets/shaders/bloom/7.blur.frag +++ b/tutorial/src/main/assets/shaders/bloom/blur.frag @@ -7,11 +7,11 @@ in vec2 TexCoords; uniform sampler2D image; uniform bool horizontal; -uniform float weight[5] = float[] (0.2270270270, 0.1945945946, 0.1216216216, 0.0540540541, 0.0162162162); +const float weight[5] = float[] (0.2270270270, 0.1945945946, 0.1216216216, 0.0540540541, 0.0162162162); void main() { - vec2 tex_offset = 1.0 / textureSize(image, 0); // gets size of single texel + vec2 tex_offset = 1.0 / vec2(textureSize(image, 0)); // gets size of single texel vec3 result = texture(image, TexCoords).rgb * weight[0]; if(horizontal) { diff --git a/tutorial/src/main/assets/shaders/bloom/7.blur.vert b/tutorial/src/main/assets/shaders/bloom/blur.vert similarity index 100% rename from tutorial/src/main/assets/shaders/bloom/7.blur.vert rename to tutorial/src/main/assets/shaders/bloom/blur.vert diff --git a/tutorial/src/main/assets/shaders/bloom/7.light_box.frag b/tutorial/src/main/assets/shaders/bloom/light_box.frag similarity index 100% rename from tutorial/src/main/assets/shaders/bloom/7.light_box.frag rename to tutorial/src/main/assets/shaders/bloom/light_box.frag diff --git a/tutorial/src/main/assets/shaders/gamma_correction/2.gamma_correction.frag b/tutorial/src/main/assets/shaders/gamma_correction/gamma_correction.frag similarity index 100% rename from tutorial/src/main/assets/shaders/gamma_correction/2.gamma_correction.frag rename to tutorial/src/main/assets/shaders/gamma_correction/gamma_correction.frag diff --git a/tutorial/src/main/assets/shaders/gamma_correction/2.gamma_correction.vert b/tutorial/src/main/assets/shaders/gamma_correction/gamma_correction.vert similarity index 100% rename from tutorial/src/main/assets/shaders/gamma_correction/2.gamma_correction.vert rename to tutorial/src/main/assets/shaders/gamma_correction/gamma_correction.vert diff --git a/tutorial/src/main/assets/shaders/hdr/6.hdr.frag b/tutorial/src/main/assets/shaders/hdr/hdr.frag similarity index 100% rename from tutorial/src/main/assets/shaders/hdr/6.hdr.frag rename to tutorial/src/main/assets/shaders/hdr/hdr.frag diff --git a/tutorial/src/main/assets/shaders/hdr/6.hdr.vert b/tutorial/src/main/assets/shaders/hdr/hdr.vert similarity index 100% rename from tutorial/src/main/assets/shaders/hdr/6.hdr.vert rename to tutorial/src/main/assets/shaders/hdr/hdr.vert diff --git a/tutorial/src/main/assets/shaders/hdr/6.lighting.frag b/tutorial/src/main/assets/shaders/hdr/lighting.frag similarity index 100% rename from tutorial/src/main/assets/shaders/hdr/6.lighting.frag rename to tutorial/src/main/assets/shaders/hdr/lighting.frag diff --git a/tutorial/src/main/assets/shaders/hdr/6.lighting.vert b/tutorial/src/main/assets/shaders/hdr/lighting.vert similarity index 100% rename from tutorial/src/main/assets/shaders/hdr/6.lighting.vert rename to tutorial/src/main/assets/shaders/hdr/lighting.vert diff --git a/tutorial/src/main/assets/shaders/light_caster/5.4.light_casters.frag b/tutorial/src/main/assets/shaders/light_caster/light_casters.frag similarity index 96% rename from tutorial/src/main/assets/shaders/light_caster/5.4.light_casters.frag rename to tutorial/src/main/assets/shaders/light_caster/light_casters.frag index 32fe2c34..294e0b16 100644 --- a/tutorial/src/main/assets/shaders/light_caster/5.4.light_casters.frag +++ b/tutorial/src/main/assets/shaders/light_caster/light_casters.frag @@ -58,9 +58,9 @@ void main() // attenuation float distance = length(light.position - FragPos); float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); - ambient *= attenuation; + ambient *= attenuation; diffuse *= attenuation; - specular *= attenuation; + specular *= attenuation; vec3 result = ambient + diffuse + specular; FragColor = vec4(result, 1.0); diff --git a/tutorial/src/main/assets/shaders/light_caster/5.4.light_casters.vert b/tutorial/src/main/assets/shaders/light_caster/light_casters.vert similarity index 100% rename from tutorial/src/main/assets/shaders/light_caster/5.4.light_casters.vert rename to tutorial/src/main/assets/shaders/light_caster/light_casters.vert diff --git a/tutorial/src/main/assets/shaders/light_caster/5.4.light_cube.frag b/tutorial/src/main/assets/shaders/light_caster/light_cube.frag similarity index 100% rename from tutorial/src/main/assets/shaders/light_caster/5.4.light_cube.frag rename to tutorial/src/main/assets/shaders/light_caster/light_cube.frag diff --git a/tutorial/src/main/assets/shaders/light_caster/5.4.light_cube.vert b/tutorial/src/main/assets/shaders/light_caster/light_cube.vert similarity index 100% rename from tutorial/src/main/assets/shaders/light_caster/5.4.light_cube.vert rename to tutorial/src/main/assets/shaders/light_caster/light_cube.vert diff --git a/tutorial/src/main/assets/shaders/multiple_lights/6.light_cube.frag b/tutorial/src/main/assets/shaders/multiple_lights/light_cube.frag similarity index 100% rename from tutorial/src/main/assets/shaders/multiple_lights/6.light_cube.frag rename to tutorial/src/main/assets/shaders/multiple_lights/light_cube.frag diff --git a/tutorial/src/main/assets/shaders/multiple_lights/6.light_cube.vert b/tutorial/src/main/assets/shaders/multiple_lights/light_cube.vert similarity index 100% rename from tutorial/src/main/assets/shaders/multiple_lights/6.light_cube.vert rename to tutorial/src/main/assets/shaders/multiple_lights/light_cube.vert diff --git a/tutorial/src/main/assets/shaders/multiple_lights/6.multiple_lights.frag b/tutorial/src/main/assets/shaders/multiple_lights/multiple_lights.frag similarity index 100% rename from tutorial/src/main/assets/shaders/multiple_lights/6.multiple_lights.frag rename to tutorial/src/main/assets/shaders/multiple_lights/multiple_lights.frag diff --git a/tutorial/src/main/assets/shaders/multiple_lights/6.multiple_lights.vert b/tutorial/src/main/assets/shaders/multiple_lights/multiple_lights.vert similarity index 100% rename from tutorial/src/main/assets/shaders/multiple_lights/6.multiple_lights.vert rename to tutorial/src/main/assets/shaders/multiple_lights/multiple_lights.vert diff --git a/tutorial/src/main/assets/shaders/phong_blinn/1.advanced_lighting.frag b/tutorial/src/main/assets/shaders/phong_blinn/advanced_lighting.frag similarity index 100% rename from tutorial/src/main/assets/shaders/phong_blinn/1.advanced_lighting.frag rename to tutorial/src/main/assets/shaders/phong_blinn/advanced_lighting.frag diff --git a/tutorial/src/main/assets/shaders/phong_blinn/1.advanced_lighting.vert b/tutorial/src/main/assets/shaders/phong_blinn/advanced_lighting.vert similarity index 100% rename from tutorial/src/main/assets/shaders/phong_blinn/1.advanced_lighting.vert rename to tutorial/src/main/assets/shaders/phong_blinn/advanced_lighting.vert diff --git a/tutorial/src/main/assets/shaders/shadow/3.1.3.debug_quad.vert b/tutorial/src/main/assets/shaders/shadow/debug_quad.vert similarity index 100% rename from tutorial/src/main/assets/shaders/shadow/3.1.3.debug_quad.vert rename to tutorial/src/main/assets/shaders/shadow/debug_quad.vert diff --git a/tutorial/src/main/assets/shaders/shadow/3.1.3.debug_quad_depth.frag b/tutorial/src/main/assets/shaders/shadow/debug_quad_depth.frag similarity index 100% rename from tutorial/src/main/assets/shaders/shadow/3.1.3.debug_quad_depth.frag rename to tutorial/src/main/assets/shaders/shadow/debug_quad_depth.frag diff --git a/tutorial/src/main/assets/shaders/shadow/3.1.3.shadow_mapping.frag b/tutorial/src/main/assets/shaders/shadow/shadow_mapping.frag similarity index 94% rename from tutorial/src/main/assets/shaders/shadow/3.1.3.shadow_mapping.frag rename to tutorial/src/main/assets/shaders/shadow/shadow_mapping.frag index 5281e1c0..1ef02c17 100644 --- a/tutorial/src/main/assets/shaders/shadow/3.1.3.shadow_mapping.frag +++ b/tutorial/src/main/assets/shaders/shadow/shadow_mapping.frag @@ -33,7 +33,7 @@ float ShadowCalculation(vec4 fragPosLightSpace) // float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0; // PCF float shadow = 0.0; - vec2 texelSize = 1.0 / textureSize(shadowMap, 0); + vec2 texelSize = 1.0 / vec2(textureSize(shadowMap, 0)); for(int x = -1; x <= 1; ++x) { for(int y = -1; y <= 1; ++y) @@ -55,9 +55,9 @@ void main() { vec3 color = texture(diffuseTexture, fs_in.TexCoords).rgb; vec3 normal = normalize(fs_in.Normal); - vec3 lightColor = vec3(0.3); + vec3 lightColor = vec3(1.0); // ambient - vec3 ambient = 0.3 * lightColor; + vec3 ambient = 0.15 * lightColor; // diffuse vec3 lightDir = normalize(lightPos - fs_in.FragPos); float diff = max(dot(lightDir, normal), 0.0); diff --git a/tutorial/src/main/assets/shaders/shadow/3.1.3.shadow_mapping.vert b/tutorial/src/main/assets/shaders/shadow/shadow_mapping.vert similarity index 100% rename from tutorial/src/main/assets/shaders/shadow/3.1.3.shadow_mapping.vert rename to tutorial/src/main/assets/shaders/shadow/shadow_mapping.vert diff --git a/tutorial/src/main/assets/shaders/shadow/3.1.3.shadow_mapping_depth.frag b/tutorial/src/main/assets/shaders/shadow/shadow_mapping_depth.frag similarity index 100% rename from tutorial/src/main/assets/shaders/shadow/3.1.3.shadow_mapping_depth.frag rename to tutorial/src/main/assets/shaders/shadow/shadow_mapping_depth.frag diff --git a/tutorial/src/main/assets/shaders/shadow/3.1.3.shadow_mapping_depth.vert b/tutorial/src/main/assets/shaders/shadow/shadow_mapping_depth.vert similarity index 100% rename from tutorial/src/main/assets/shaders/shadow/3.1.3.shadow_mapping_depth.vert rename to tutorial/src/main/assets/shaders/shadow/shadow_mapping_depth.vert diff --git a/tutorial/src/main/assets/shaders/ssao/9.ssao.frag b/tutorial/src/main/assets/shaders/ssao/ssao.frag similarity index 95% rename from tutorial/src/main/assets/shaders/ssao/9.ssao.frag rename to tutorial/src/main/assets/shaders/ssao/ssao.frag index 381d3519..2079e9fc 100644 --- a/tutorial/src/main/assets/shaders/ssao/9.ssao.frag +++ b/tutorial/src/main/assets/shaders/ssao/ssao.frag @@ -16,7 +16,7 @@ float radius = 0.5; float bias = 0.025; // tile noise texture over screen based on screen dimensions divided by noise size -const vec2 noiseScale = vec2(800.0/4.0, 600.0/4.0); +uniform vec2 noiseScale; uniform mat4 projection; @@ -51,7 +51,7 @@ void main() float rangeCheck = smoothstep(0.0, 1.0, radius / abs(fragPos.z - sampleDepth)); occlusion += (sampleDepth >= samplePos.z + bias ? 1.0 : 0.0) * rangeCheck; } - occlusion = 1.0 - (occlusion / kernelSize); + occlusion = 1.0 - occlusion / float(kernelSize); FragColor = occlusion; } diff --git a/tutorial/src/main/assets/shaders/ssao/9.ssao.vert b/tutorial/src/main/assets/shaders/ssao/ssao.vert similarity index 100% rename from tutorial/src/main/assets/shaders/ssao/9.ssao.vert rename to tutorial/src/main/assets/shaders/ssao/ssao.vert diff --git a/tutorial/src/main/assets/shaders/ssao/9.ssao_blur.frag b/tutorial/src/main/assets/shaders/ssao/ssao_blur.frag similarity index 100% rename from tutorial/src/main/assets/shaders/ssao/9.ssao_blur.frag rename to tutorial/src/main/assets/shaders/ssao/ssao_blur.frag diff --git a/tutorial/src/main/assets/shaders/ssao/9.ssao_geometry.frag b/tutorial/src/main/assets/shaders/ssao/ssao_geometry.frag similarity index 100% rename from tutorial/src/main/assets/shaders/ssao/9.ssao_geometry.frag rename to tutorial/src/main/assets/shaders/ssao/ssao_geometry.frag diff --git a/tutorial/src/main/assets/shaders/ssao/9.ssao_geometry.vert b/tutorial/src/main/assets/shaders/ssao/ssao_geometry.vert similarity index 100% rename from tutorial/src/main/assets/shaders/ssao/9.ssao_geometry.vert rename to tutorial/src/main/assets/shaders/ssao/ssao_geometry.vert diff --git a/tutorial/src/main/assets/shaders/ssao/9.ssao_lighting.frag b/tutorial/src/main/assets/shaders/ssao/ssao_lighting.frag similarity index 100% rename from tutorial/src/main/assets/shaders/ssao/9.ssao_lighting.frag rename to tutorial/src/main/assets/shaders/ssao/ssao_lighting.frag diff --git a/tutorial/src/main/cpp/TargetCamera.cpp b/tutorial/src/main/cpp/TargetCamera.cpp index 186e1573..fcd7dc7a 100644 --- a/tutorial/src/main/cpp/TargetCamera.cpp +++ b/tutorial/src/main/cpp/TargetCamera.cpp @@ -100,6 +100,8 @@ void TargetCamera::update() { glm::to_string(m_up).c_str()); m_viewMatrix = glm::lookAt(m_position, m_targetPosition, m_up); + m_front = glm::normalize(m_targetPosition - m_position); + m_right = glm::normalize(glm::cross(m_front, m_up)); viewDirty = false; } if (projectionDirty) { diff --git a/tutorial/src/main/cpp/lighting/BasicLightingScene.cpp b/tutorial/src/main/cpp/lighting/BasicLightingScene.cpp index 79733d9e..ee851949 100644 --- a/tutorial/src/main/cpp/lighting/BasicLightingScene.cpp +++ b/tutorial/src/main/cpp/lighting/BasicLightingScene.cpp @@ -4,8 +4,10 @@ #include "Camera.h" #include "TargetCamera.h" #include "Texture.h" +#include "glerror.h" BasicLightingScene::BasicLightingScene() { + m_lightPos = glm::vec3(1.2f, 1.0f, 2.0f); } void BasicLightingScene::init() { @@ -26,20 +28,23 @@ void BasicLightingScene::init() { // ------------------------------------------------------------------ float vertices[] = { // positions // normals // texture coords - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, - + // front face -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + // back face + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + + // left face -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, @@ -47,24 +52,27 @@ void BasicLightingScene::init() { -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + // right face + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + // bottom face -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + // top face -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f }; @@ -76,11 +84,11 @@ void BasicLightingScene::init() { glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBindVertexArray(m_cubeVAO); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *) 0); glEnableVertexAttribArray(0); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *) (3 * sizeof(float))); glEnableVertexAttribArray(1); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *) (6 * sizeof(float))); glEnableVertexAttribArray(2); // second, configure the light's VAO (VBO stays the same; the vertices are the same for the light object which is also a 3D cube) @@ -89,7 +97,7 @@ void BasicLightingScene::init() { glBindBuffer(GL_ARRAY_BUFFER, m_VBO); // note that we update the lamp's position attribute's stride to reflect the updated buffer data - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *) 0); glEnableVertexAttribArray(0); // load textures @@ -102,6 +110,8 @@ void BasicLightingScene::init() { m_pLightingShader->setInt("material.diffuse", 0); m_pLightingShader->setInt("material.specular", 1); m_pLightingShader->setInt("material.emission", 2); + + check_gl_error(); } void BasicLightingScene::resize(int width, int height) { @@ -116,6 +126,10 @@ void BasicLightingScene::draw() { glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + // view/projection transformations + glm::mat4 projection = m_camera->getProjectionMatrix(); + glm::mat4 view = m_camera->getViewMatrix(); + // be sure to activate shader when setting uniforms/drawing objects if(m_pLightingShader) { @@ -124,16 +138,14 @@ void BasicLightingScene::draw() { m_pLightingShader->setVec3("viewPos", m_camera->getPosition()); // light properties - m_pLightingShader->setVec3("light.ambient", 0.2f, 0.2f, 0.2f); - m_pLightingShader->setVec3("light.diffuse", 0.5f, 0.5f, 0.5f); - m_pLightingShader->setVec3("light.specular", 1.0f, 1.0f, 1.0f); + m_pLightingShader->setVec3("light.ambient", ambientFactor, ambientFactor, ambientFactor); + m_pLightingShader->setVec3("light.diffuse", diffuseFactor, diffuseFactor, diffuseFactor); + m_pLightingShader->setVec3("light.specular", specularFactor, specularFactor, specularFactor); // material properties - m_pLightingShader->setFloat("material.shininess", 64.0f); + m_pLightingShader->setFloat("material.shininess", 64.f * 64.f); + - // view/projection transformations - glm::mat4 projection = m_camera->getProjectionMatrix(); - glm::mat4 view = m_camera->getViewMatrix(); m_pLightingShader->setMat4("projection", projection); m_pLightingShader->setMat4("view", view); @@ -154,39 +166,38 @@ void BasicLightingScene::draw() { // render the cube glBindVertexArray(m_cubeVAO); glDrawArrays(GL_TRIANGLES, 0, 36); + } - // also draw the lamp object - if(m_pLightCubeShader) - { - m_pLightCubeShader->use(); - m_pLightCubeShader->setMat4("projection", projection); - m_pLightCubeShader->setMat4("view", view); - model = glm::mat4(1.0f); - model = glm::translate(model, m_lightPos); - model = glm::scale(model, glm::vec3(0.2f)); // a smaller cube - m_pLightCubeShader->setMat4("model", model); - - glBindVertexArray(m_lightCubeVAO); - glDrawArrays(GL_TRIANGLES, 0, 36); - } + // also draw the lamp object + if (m_pLightCubeShader) { + m_pLightCubeShader->use(); + m_pLightCubeShader->setMat4("projection", projection); + m_pLightCubeShader->setMat4("view", view); + glm::mat model = glm::mat4(1.0f); + model = glm::translate(model, m_lightPos); + model = glm::scale(model, glm::vec3(0.2f)); // a smaller cube + m_pLightCubeShader->setMat4("model", model); + + glBindVertexArray(m_lightCubeVAO); + glDrawArrays(GL_TRIANGLES, 0, 36); } + check_gl_error(); } void BasicLightingScene::destroy() { glDeleteVertexArrays(1, &m_cubeVAO); glDeleteVertexArrays(1, &m_lightCubeVAO); glDeleteBuffers(1, &m_VBO); - if (m_pLightingShader) - { + if (m_pLightingShader) { delete m_pLightingShader; m_pLightingShader = nullptr; } - if (m_pLightCubeShader) - { + if (m_pLightCubeShader) { delete m_pLightCubeShader; m_pLightCubeShader = nullptr; } delete m_camera; + check_gl_error(); } BasicLightingScene::~BasicLightingScene() { @@ -201,16 +212,39 @@ std::map BasicLightingScene::propertyEvent(std::mapsecond.type() == typeid(float)) { + ambientFactor = std::any_cast(it->second); + } else if (it->second.type() == typeid(double)) { + ambientFactor = (float)std::any_cast(it->second); + } + } + if (auto it = map.find("diffuseFactor"); it != map.end()) { + if (it->second.type() == typeid(float)) { + diffuseFactor = std::any_cast(it->second); + } else if (it->second.type() == typeid(double)) { + diffuseFactor = (float)std::any_cast(it->second); + } + } + if (auto it = map.find("specularFactor"); it != map.end()) { + if (it->second.type() == typeid(float)) { + specularFactor = std::any_cast(it->second); + } else if (it->second.type() == typeid(double)) { + specularFactor = (float)std::any_cast(it->second); + } + } + return {}; } void BasicLightingScene::parseTargetCameraEvent(std::map &event) { - auto* targetCamera = dynamic_cast(m_camera); + auto *targetCamera = dynamic_cast(m_camera); if (!targetCamera) return; if (auto it = event.find("single_touching"); it != event.end()) { if (it->second.type() == typeid(std::vector)) { - const auto& val = std::any_cast&>(it->second); + const auto &val = std::any_cast &>(it->second); if (val.size() >= 4) { targetCamera->onSingleTouching(glm::vec2(val[0], val[1]), glm::vec2(val[2], val[3])); } @@ -219,10 +253,10 @@ void BasicLightingScene::parseTargetCameraEvent(std::map if (auto it = event.find("double_touching"); it != event.end()) { if (it->second.type() == typeid(std::vector)) { - const auto& val = std::any_cast&>(it->second); + const auto &val = std::any_cast &>(it->second); if (val.size() >= 8) { targetCamera->onDoubleTouching(glm::vec2(val[0], val[1]), glm::vec2(val[2], val[3]), - glm::vec2(val[4], val[5]), glm::vec2(val[6], val[7])); + glm::vec2(val[4], val[5]), glm::vec2(val[6], val[7])); } } } diff --git a/tutorial/src/main/cpp/lighting/BasicLightingScene.h b/tutorial/src/main/cpp/lighting/BasicLightingScene.h index 7637857a..f663814b 100644 --- a/tutorial/src/main/cpp/lighting/BasicLightingScene.h +++ b/tutorial/src/main/cpp/lighting/BasicLightingScene.h @@ -36,6 +36,12 @@ public : unsigned int m_emissionMap = 0u; glm::vec3 m_lightPos; + //region Properties + float ambientFactor = 0.35f; + float diffuseFactor = 0.5f; + float specularFactor = 1.0f; + //endregion + void parseTargetCameraEvent(std::map &event); }; diff --git a/tutorial/src/main/cpp/lighting/BloomScene.cpp b/tutorial/src/main/cpp/lighting/BloomScene.cpp index 91349ca8..f18e4dbf 100644 --- a/tutorial/src/main/cpp/lighting/BloomScene.cpp +++ b/tutorial/src/main/cpp/lighting/BloomScene.cpp @@ -11,19 +11,20 @@ void BloomScene::init() { m_camera = new TargetCamera; // configure global opengl state // ----------------------------- + glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); // build and compile shaders // ------------------------- - m_pShader = new Shader("7.bloom.vert", "7.bloom.frag"); - m_pShaderLight = new Shader("7.bloom.vert", "7.light_box.frag"); - m_pShaderBlur = new Shader("7.blur.vert", "7.blur.frag"); - m_pShaderBloomFinal = new Shader("7.bloom_final.vert", "7.bloom_final.frag"); + m_pShader = new Shader("shaders/bloom/bloom.vert", "shaders/bloom/bloom.frag"); + m_pShaderLight = new Shader("shaders/bloom/bloom.vert", "shaders/bloom/light_box.frag"); + m_pShaderBlur = new Shader("shaders/bloom/blur.vert", "shaders/bloom/blur.frag"); + m_pShaderBloomFinal = new Shader("shaders/bloom/bloom_final.vert", "shaders/bloom/bloom_final.frag"); // load textures // ------------- - m_woodTexture = loadTexture("resources/textures/wood.png", true); // note that we're loading the texture as an SRGB texture - m_containerTexture = loadTexture("resources/textures/container2.png", true); // note that we're loading the texture as an SRGB texture + m_woodTexture = loadTexture("textures/wood.png", true); // note that we're loading the texture as an SRGB texture + m_containerTexture = loadTexture("textures/container2.png", true); // note that we're loading the texture as an SRGB texture // configure (floating point) framebuffers // --------------------------------------- @@ -34,7 +35,7 @@ void BloomScene::init() { for (unsigned int i = 0; i < 2; i++) { glBindTexture(GL_TEXTURE_2D, m_colorBuffers[i]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 800, 600, 0, GL_RGBA, GL_FLOAT, nullptr); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_FLOAT, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // we clamp to the edge as the blur filter would otherwise sample repeated texture values! @@ -45,7 +46,7 @@ void BloomScene::init() { // create and attach depth buffer (renderbuffer) glGenRenderbuffers(1, &m_rboDepth); glBindRenderbuffer(GL_RENDERBUFFER, m_rboDepth); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 800, 600); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_WIDTH, SCR_HEIGHT); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_rboDepth); // tell OpenGL which color attachments we'll use (of this framebuffer) for rendering unsigned int attachments[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; @@ -62,7 +63,7 @@ void BloomScene::init() { { glBindFramebuffer(GL_FRAMEBUFFER, m_pingpongFBO[i]); glBindTexture(GL_TEXTURE_2D, m_pingpongColorbuffers[i]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 800, 600, 0, GL_RGBA, GL_FLOAT, nullptr); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_FLOAT, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // we clamp to the edge as the blur filter would otherwise sample repeated texture values! @@ -99,6 +100,8 @@ void BloomScene::init() { void BloomScene::resize(int width, int height) { m_camera->setAspec((float) width / (float) height); glViewport(0, 0, width, height); + m_width = width; + m_height = height; } void BloomScene::draw() { @@ -112,6 +115,7 @@ void BloomScene::draw() { // ----------------------------------------------- glBindFramebuffer(GL_FRAMEBUFFER, m_hdrFBO); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); glm::mat4 projection = m_camera->getProjectionMatrix(); glm::mat4 view = m_camera->getViewMatrix(); glm::mat4 model = glm::mat4(1.0f); @@ -217,6 +221,7 @@ void BloomScene::draw() { // 3. now render floating point color buffer to 2D quad and tonemap HDR colors to default framebuffer's (clamped) color range // -------------------------------------------------------------------------------------------------------------------------- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glViewport(0, 0, m_width, m_height); if(m_pShaderBloomFinal) { m_pShaderBloomFinal->use(); @@ -317,10 +322,10 @@ void BloomScene::renderQuad() { { float quadVertices[] = { // positions // texture Coords - -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // Bottom Left + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // Bottom Right + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top Left + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Top Right }; // setup plane VAO glGenVertexArrays(1, &m_quadVAO); @@ -343,48 +348,48 @@ void BloomScene::renderCube() { if (m_cubeVAO == 0) { float vertices[] = { - // back face + // back face (CCW viewed from back, so CW from front) -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left - 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right - 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, // bottom-right - 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right + 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, // top-left // front face -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left - 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // bottom-right - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right + 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // top-left -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left // left face -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right - -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-left -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left + -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-left -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left - -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-right -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right + -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-right // right face - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left - 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right - 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-right - 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left - 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-left + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left + 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-right + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right + 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-left + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left // bottom face -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right - 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, // top-left - 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left - 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left - -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-right + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left + 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, // top-left + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right + -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-right // top face -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left - 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right - 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right - 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right - -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left - -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f // bottom-left + 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right + -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, // bottom-left + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f // top-left }; glGenVertexArrays(1, &m_cubeVAO); glGenBuffers(1, &m_cubeVBO); diff --git a/tutorial/src/main/cpp/lighting/BloomScene.h b/tutorial/src/main/cpp/lighting/BloomScene.h index 483e8c0f..e7ff1c1f 100644 --- a/tutorial/src/main/cpp/lighting/BloomScene.h +++ b/tutorial/src/main/cpp/lighting/BloomScene.h @@ -24,6 +24,9 @@ public : virtual ~BloomScene(); + static constexpr unsigned int SCR_WIDTH = 800; + static constexpr unsigned int SCR_HEIGHT = 600; + private: void renderQuad(); void renderCube(); @@ -51,9 +54,10 @@ public : std::vector m_lightPositions; std::vector m_lightColors; + int m_width = 0, m_height = 0; bool bloom = false; - float exposure = 0.f; + float exposure = 1.0f; void parseTargetCameraEvent(std::map &event); }; diff --git a/tutorial/src/main/cpp/lighting/GammaCorrectionScene.cpp b/tutorial/src/main/cpp/lighting/GammaCorrectionScene.cpp index 97617a1d..aaccbef0 100644 --- a/tutorial/src/main/cpp/lighting/GammaCorrectionScene.cpp +++ b/tutorial/src/main/cpp/lighting/GammaCorrectionScene.cpp @@ -18,8 +18,8 @@ void GammaCorrectionScene::init() { // build and compile shaders // ------------------------- - m_pShader = new Shader("shaders/gamma_correction/2.gamma_correction.vert", - "shaders/gamma_correction/2.gamma_correction.frag"); + m_pShader = new Shader("shaders/gamma_correction/gamma_correction.vert", + "shaders/gamma_correction/gamma_correction.frag"); // set up vertex data (and buffer(s)) and configure vertex attributes // ------------------------------------------------------------------ diff --git a/tutorial/src/main/cpp/lighting/GammaCorrectionScene.h b/tutorial/src/main/cpp/lighting/GammaCorrectionScene.h index db1823ad..16caf6b4 100644 --- a/tutorial/src/main/cpp/lighting/GammaCorrectionScene.h +++ b/tutorial/src/main/cpp/lighting/GammaCorrectionScene.h @@ -32,7 +32,10 @@ public : glm::vec3 m_lightPositions[4]; glm::vec3 m_lightColors[4]; + + //region properties bool gammaEnabled = false; + //endregion void parseTargetCameraEvent(std::map &event); public: diff --git a/tutorial/src/main/cpp/lighting/HdrScene.cpp b/tutorial/src/main/cpp/lighting/HdrScene.cpp index 170330e3..1da99d37 100644 --- a/tutorial/src/main/cpp/lighting/HdrScene.cpp +++ b/tutorial/src/main/cpp/lighting/HdrScene.cpp @@ -10,15 +10,22 @@ HdrScene::HdrScene() { } void HdrScene::init() { - m_camera = new TargetCamera; + m_camera = new Camera; + m_cameraZ = 0.0f; + m_camera->setPosition(glm::vec3(0.0f, 0.0f, m_cameraZ)); + m_camera->setTargetPosition(glm::vec3(0.0f, 0.0f, -50.0f)); + m_camera->setUp(glm::vec3(0.0f, 1.0f, 0.0f)); + m_camera->start(); + // configure global opengl state // ----------------------------- + glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); // build and compile shaders // ------------------------- - m_pShader = new Shader("shaders/hdr/6.lighting.vert", "shaders/hdr/6.lighting.frag"); - m_pHdrShader = new Shader("shaders/hdr/6.hdr.vert", "shaders/hdr/6.hdr.frag"); + m_pShader = new Shader("shaders/hdr/lighting.vert", "shaders/hdr/lighting.frag"); + m_pHdrShader = new Shader("shaders/hdr/hdr.vert", "shaders/hdr/hdr.frag"); // load textures // ------------- @@ -30,13 +37,13 @@ void HdrScene::init() { // create floating point color buffer glGenTextures(1, &m_colorBuffer); glBindTexture(GL_TEXTURE_2D, m_colorBuffer); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 800, 600, 0, GL_RGBA, GL_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // create depth buffer (renderbuffer) glGenRenderbuffers(1, &m_rboDepth); glBindRenderbuffer(GL_RENDERBUFFER, m_rboDepth); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 800, 600); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_WIDTH, SCR_HEIGHT); // attach buffers glBindFramebuffer(GL_FRAMEBUFFER, m_hdrFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer, 0); @@ -48,7 +55,7 @@ void HdrScene::init() { // lighting info // ------------- // positions - m_lightPositions.push_back(glm::vec3( 0.0f, 0.0f, 49.5f)); // back light + m_lightPositions.push_back(glm::vec3( 0.0f, 0.0f, 25.0f)); m_lightPositions.push_back(glm::vec3(-1.4f, -1.9f, 9.0f)); m_lightPositions.push_back(glm::vec3( 0.0f, -1.8f, 4.0f)); m_lightPositions.push_back(glm::vec3( 0.8f, -1.7f, 6.0f)); @@ -69,19 +76,24 @@ void HdrScene::init() { void HdrScene::resize(int width, int height) { m_camera->setAspec((float) width / (float) height); glViewport(0, 0, width, height); + m_width = width; + m_height = height; } void HdrScene::draw() { + m_camera->setPosition(glm::vec3(0.0f, 0.0f, m_cameraZ)); + m_camera->setTargetPosition(glm::vec3(0.0f, 0.0f, m_cameraZ - 1.0f)); m_camera->update(); // render // ------ - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 1. render scene into floating point framebuffer // ----------------------------------------------- glBindFramebuffer(GL_FRAMEBUFFER, m_hdrFBO); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); glm::mat4 projection = m_camera->getProjectionMatrix(); glm::mat4 view = m_camera->getViewMatrix(); if(m_pShader) @@ -111,6 +123,7 @@ void HdrScene::draw() { // 2. now render floating point color buffer to 2D quad and tonemap HDR colors to default framebuffer's (clamped) color range // -------------------------------------------------------------------------------------------------------------------------- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glViewport(0, 0, m_width, m_height); if(m_pHdrShader) { m_pHdrShader->use(); @@ -152,37 +165,23 @@ std::map HdrScene::propertyEvent(std::mapsecond.type() == typeid(std::string)) { auto eventIdStr = std::any_cast(eventIdIt->second); if ("target_camera_touching_event" == eventIdStr) { - parseTargetCameraEvent(map); + if (auto it = map.find("single_touching"); it != map.end()) { + if (it->second.type() == typeid(std::vector)) { + const auto& val = std::any_cast&>(it->second); + if (val.size() >= 4) { + float dy = val[3] - val[1]; + m_cameraZ -= dy * 0.05f; // Adjust sensitivity as needed + } + } + } } } return {}; } void HdrScene::parseTargetCameraEvent(std::map &event) { - auto* targetCamera = dynamic_cast(m_camera); - if (!targetCamera) return; - - if (auto it = event.find("single_touching"); it != event.end()) { - if (it->second.type() == typeid(std::vector)) { - const auto& val = std::any_cast&>(it->second); - if (val.size() >= 4) { - targetCamera->onSingleTouching(glm::vec2(val[0], val[1]), glm::vec2(val[2], val[3])); - } - } - } - - if (auto it = event.find("double_touching"); it != event.end()) { - if (it->second.type() == typeid(std::vector)) { - const auto& val = std::any_cast&>(it->second); - if (val.size() >= 8) { - targetCamera->onDoubleTouching(glm::vec2(val[0], val[1]), glm::vec2(val[2], val[3]), - glm::vec2(val[4], val[5]), glm::vec2(val[6], val[7])); - } - } - } - if (event.find("reset") != event.end()) { - targetCamera->reset(); + m_cameraZ = 0.0f; } } @@ -191,10 +190,10 @@ void HdrScene::renderQuad() { { float quadVertices[] = { // positions // texture Coords - -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, }; // setup plane VAO glGenVertexArrays(1, &m_quadVAO); @@ -217,48 +216,48 @@ void HdrScene::renderCube() { if (m_cubeVAO == 0) { float vertices[] = { - // back face - -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left - 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right - 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, // bottom-right - 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right - -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left - -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, // top-left - // front face - -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left - 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // bottom-right - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right - -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // top-left - -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left - // left face - -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right - -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-left - -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left - -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left - -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-right - -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right - // right face - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left - 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right - 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-right - 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left - 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-left - // bottom face - -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right - 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, // top-left - 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left - 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left - -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-right - -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right - // top face - -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left - 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right - 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right - 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right - -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left - -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f // bottom-left + // back face (viewed from inside) + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left + 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right + -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // top-left + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left + // front face (viewed from inside) + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right + 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left + -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, // top-left + // left face (viewed from inside) + -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right + -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-left + -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left + -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left + -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-right + -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right + // right face (viewed from inside) + 1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left + 1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right + 1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-right + 1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right + 1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left + 1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-left + // top face (viewed from inside) + -1.0f, 1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-left + 1.0f, 1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, // top-right + 1.0f, 1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-right + -1.0f, 1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-left + -1.0f, 1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-left + // bottom face (viewed from inside) + -1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-right + 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-left + 1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-left + 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-left + -1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f // top-right + -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, // bottom-right }; glGenVertexArrays(1, &m_cubeVAO); glGenBuffers(1, &m_cubeVBO); diff --git a/tutorial/src/main/cpp/lighting/HdrScene.h b/tutorial/src/main/cpp/lighting/HdrScene.h index 26f64440..8744af38 100644 --- a/tutorial/src/main/cpp/lighting/HdrScene.h +++ b/tutorial/src/main/cpp/lighting/HdrScene.h @@ -25,6 +25,9 @@ public : virtual ~HdrScene(); private: + static constexpr unsigned int SCR_WIDTH = 800; + static constexpr unsigned int SCR_HEIGHT = 600; + void renderQuad(); void renderCube(); @@ -48,6 +51,9 @@ public : bool hdr = false; float exposure = 0.f; + float m_cameraZ = 0.0f; + int m_width = 0, m_height = 0; + void parseTargetCameraEvent(std::map &event); }; diff --git a/tutorial/src/main/cpp/lighting/LightCasterScene.cpp b/tutorial/src/main/cpp/lighting/LightCasterScene.cpp index 115f1086..a35ea0ec 100644 --- a/tutorial/src/main/cpp/lighting/LightCasterScene.cpp +++ b/tutorial/src/main/cpp/lighting/LightCasterScene.cpp @@ -25,8 +25,10 @@ void LightCasterScene::init() { // build and compile our shader zprogram // ------------------------------------ - m_pLightingShader = new Shader("shaders/light_caster/5.4.light_casters.vert", "shaders/light_caster/5.4.light_casters.frag"); - m_pLightCubeShader = new Shader("shaders/light_caster/5.4.light_cube.vert", "shaders/light_caster/5.4.light_cube.frag"); + m_pLightingShader = new Shader("shaders/light_caster/light_casters.vert", + "shaders/light_caster/light_casters.frag"); + m_pLightCubeShader = new Shader("shaders/light_caster/light_cube.vert", + "shaders/light_caster/light_cube.frag"); // set up vertex data (and buffer(s)) and configure vertex attributes // ------------------------------------------------------------------ @@ -126,14 +128,14 @@ void LightCasterScene::draw() { m_pLightingShader->use(); m_pLightingShader->setVec3("light.position", m_camera->getPosition()); m_pLightingShader->setVec3("light.direction", m_camera->getFront()); - m_pLightingShader->setFloat("light.cutOff", glm::cos(glm::radians(12.5f))); - m_pLightingShader->setFloat("light.outerCutOff", glm::cos(glm::radians(17.5f))); + m_pLightingShader->setFloat("light.cutOff", glm::cos(glm::radians(6.5f))); + m_pLightingShader->setFloat("light.outerCutOff", glm::cos(glm::radians(9.5f))); m_pLightingShader->setVec3("viewPos", m_camera->getPosition()); // light properties - m_pLightingShader->setVec3("light.ambient", 0.1f, 0.1f, 0.1f); - m_pLightingShader->setVec3("light.diffuse", 0.8f, 0.8f, 0.8f); - m_pLightingShader->setVec3("light.specular", 1.0f, 1.0f, 1.0f); + m_pLightingShader->setVec3("light.ambient", ambientFactor, ambientFactor, ambientFactor); + m_pLightingShader->setVec3("light.diffuse", diffuseFactor, diffuseFactor, diffuseFactor); + m_pLightingShader->setVec3("light.specular", specularFactor, specularFactor, specularFactor); m_pLightingShader->setFloat("light.constant", 1.0f); m_pLightingShader->setFloat("light.linear", 0.09f); m_pLightingShader->setFloat("light.quadratic", 0.032f); @@ -202,6 +204,29 @@ std::map LightCasterScene::propertyEvent(std::mapsecond.type() == typeid(float)) { + ambientFactor = std::any_cast(it->second); + } else if (it->second.type() == typeid(double)) { + ambientFactor = (float)std::any_cast(it->second); + } + } + if (auto it = map.find("diffuseFactor"); it != map.end()) { + if (it->second.type() == typeid(float)) { + diffuseFactor = std::any_cast(it->second); + } else if (it->second.type() == typeid(double)) { + diffuseFactor = (float)std::any_cast(it->second); + } + } + if (auto it = map.find("specularFactor"); it != map.end()) { + if (it->second.type() == typeid(float)) { + specularFactor = std::any_cast(it->second); + } else if (it->second.type() == typeid(double)) { + specularFactor = (float)std::any_cast(it->second); + } + } + return {}; } diff --git a/tutorial/src/main/cpp/lighting/LightCasterScene.h b/tutorial/src/main/cpp/lighting/LightCasterScene.h index 5a48589e..82d403f2 100644 --- a/tutorial/src/main/cpp/lighting/LightCasterScene.h +++ b/tutorial/src/main/cpp/lighting/LightCasterScene.h @@ -36,6 +36,12 @@ public : unsigned int m_specularMap = 0u; glm::vec3 m_cubePositions[10]; + //region Properties + float ambientFactor = 0.35f; + float diffuseFactor = 0.5f; + float specularFactor = 1.0f; + //endregion + void parseTargetCameraEvent(std::map &event); }; diff --git a/tutorial/src/main/cpp/lighting/MultiLightsScene.cpp b/tutorial/src/main/cpp/lighting/MultiLightsScene.cpp index 4740fe98..0b23944e 100644 --- a/tutorial/src/main/cpp/lighting/MultiLightsScene.cpp +++ b/tutorial/src/main/cpp/lighting/MultiLightsScene.cpp @@ -30,8 +30,10 @@ void MultiLightsScene::init() { // build and compile our shader zprogram // ------------------------------------ - m_pLightingShader = new Shader("shaders/multiple_lights/multiple_lights.vert", "shaders/multiple_lights/multiple_lights.frag"); - m_pLightCubeShader = new Shader("shaders/multiple_lights/light_cube.vert", "shaders/multiple_lights/light_cube.frag"); + m_pLightingShader = new Shader("shaders/multiple_lights/multiple_lights.vert", + "shaders/multiple_lights/multiple_lights.frag"); + m_pLightCubeShader = new Shader("shaders/multiple_lights/light_cube.vert", + "shaders/multiple_lights/light_cube.frag"); // set up vertex data (and buffer(s)) and configure vertex attributes // ------------------------------------------------------------------ diff --git a/tutorial/src/main/cpp/lighting/PhongVsBlinnScene.cpp b/tutorial/src/main/cpp/lighting/PhongVsBlinnScene.cpp index 0dfc65fe..a01b25b2 100644 --- a/tutorial/src/main/cpp/lighting/PhongVsBlinnScene.cpp +++ b/tutorial/src/main/cpp/lighting/PhongVsBlinnScene.cpp @@ -2,7 +2,7 @@ #include "Shader.h" #include "Camera.h" - #include "TargetCamera.h" +#include "TargetCamera.h" #include "Texture.h" PhongVsBlinnScene::PhongVsBlinnScene() { @@ -10,28 +10,30 @@ PhongVsBlinnScene::PhongVsBlinnScene() { void PhongVsBlinnScene::init() { m_camera = new TargetCamera; + m_lightPos = glm::vec3(0.0f, 0.0f, 0.0f); // configure global opengl state // ----------------------------- + glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +// glEnable(GL_BLEND); +// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // build and compile our shader zprogram // ------------------------------------ - m_pShader = new Shader("shaders/phong_blinn/1.advanced_lighting.vert", - "shaders/phong_blinn/1.advanced_lighting.frag"); + m_pShader = new Shader("shaders/phong_blinn/advanced_lighting.vert", + "shaders/phong_blinn/advanced_lighting.frag"); // set up vertex data (and buffer(s)) and configure vertex attributes // ------------------------------------------------------------------ float planeVertices[] = { // positions // normals // texcoords - 10.0f, -0.5f, 10.0f, 0.0f, 1.0f, 0.0f, 10.0f, 0.0f, - -10.0f, -0.5f, 10.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, - -10.0f, -0.5f, -10.0f, 0.0f, 1.0f, 0.0f, 0.0f, 10.0f, + -10.0f, -0.5f, 10.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, + 10.0f, -0.5f, 10.0f, 0.0f, 1.0f, 0.0f, 10.0f, 0.0f, + 10.0f, -0.5f, -10.0f, 0.0f, 1.0f, 0.0f, 10.0f, 10.0f, - 10.0f, -0.5f, 10.0f, 0.0f, 1.0f, 0.0f, 10.0f, 0.0f, - -10.0f, -0.5f, -10.0f, 0.0f, 1.0f, 0.0f, 0.0f, 10.0f, - 10.0f, -0.5f, -10.0f, 0.0f, 1.0f, 0.0f, 10.0f, 10.0f + -10.0f, -0.5f, 10.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, + 10.0f, -0.5f, -10.0f, 0.0f, 1.0f, 0.0f, 10.0f, 10.0f, + -10.0f, -0.5f, -10.0f, 0.0f, 1.0f, 0.0f, 0.0f, 10.0f }; // plane VAO glGenVertexArrays(1, &m_planeVAO); @@ -40,11 +42,11 @@ void PhongVsBlinnScene::init() { glBindBuffer(GL_ARRAY_BUFFER, m_planeVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), planeVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *) 0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *) (3 * sizeof(float))); glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *) (6 * sizeof(float))); glBindVertexArray(0); // load textures @@ -53,8 +55,8 @@ void PhongVsBlinnScene::init() { // shader configuration // -------------------- - m_pShader->use(); - m_pShader->setInt("texture1", 0); +// m_pShader->use(); +// m_pShader->setInt("texture1", 0); } void PhongVsBlinnScene::resize(int width, int height) { @@ -70,8 +72,7 @@ void PhongVsBlinnScene::draw() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // draw objects - if(m_pShader) - { + if (m_pShader) { m_pShader->use(); glm::mat4 projection = m_camera->getProjectionMatrix(); glm::mat4 view = m_camera->getViewMatrix(); @@ -83,8 +84,7 @@ void PhongVsBlinnScene::draw() { m_pShader->setInt("blinn", blinn); // floor glBindVertexArray(m_planeVAO); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, m_floorTexture); + m_pShader->setTexture("floorTexture", m_floorTexture, 0); glDrawArrays(GL_TRIANGLES, 0, 6); } } @@ -92,8 +92,7 @@ void PhongVsBlinnScene::draw() { void PhongVsBlinnScene::destroy() { glDeleteVertexArrays(1, &m_planeVAO); glDeleteBuffers(1, &m_planeVBO); - if (m_pShader) - { + if (m_pShader) { delete m_pShader; m_pShader = nullptr; } @@ -111,17 +110,28 @@ std::map PhongVsBlinnScene::propertyEvent(std::map &event) { + if (auto it = event.find("on"); it != event.end()) { + if (it->second.type() == typeid(bool)) { + blinn = std::any_cast(it->second); + } + } +} + void PhongVsBlinnScene::parseTargetCameraEvent(std::map &event) { - auto* targetCamera = dynamic_cast(m_camera); + auto *targetCamera = dynamic_cast(m_camera); if (!targetCamera) return; if (auto it = event.find("single_touching"); it != event.end()) { if (it->second.type() == typeid(std::vector)) { - const auto& val = std::any_cast&>(it->second); + const auto &val = std::any_cast &>(it->second); if (val.size() >= 4) { targetCamera->onSingleTouching(glm::vec2(val[0], val[1]), glm::vec2(val[2], val[3])); } @@ -130,10 +140,10 @@ void PhongVsBlinnScene::parseTargetCameraEvent(std::map & if (auto it = event.find("double_touching"); it != event.end()) { if (it->second.type() == typeid(std::vector)) { - const auto& val = std::any_cast&>(it->second); + const auto &val = std::any_cast &>(it->second); if (val.size() >= 8) { targetCamera->onDoubleTouching(glm::vec2(val[0], val[1]), glm::vec2(val[2], val[3]), - glm::vec2(val[4], val[5]), glm::vec2(val[6], val[7])); + glm::vec2(val[4], val[5]), glm::vec2(val[6], val[7])); } } } diff --git a/tutorial/src/main/cpp/lighting/PhongVsBlinnScene.h b/tutorial/src/main/cpp/lighting/PhongVsBlinnScene.h index 71da98b8..eea1e2e5 100644 --- a/tutorial/src/main/cpp/lighting/PhongVsBlinnScene.h +++ b/tutorial/src/main/cpp/lighting/PhongVsBlinnScene.h @@ -22,6 +22,10 @@ public : std::map propertyEvent(std::map &map) override; + bool isBlinn() const; + + void setBlinn(bool blinn); + virtual ~PhongVsBlinnScene(); private: @@ -32,13 +36,14 @@ public : unsigned int m_floorTexture = 0u; glm::vec3 m_lightPos; + //region properties bool blinn = true; + //endregion + void parseTargetCameraEvent(std::map &event); -public: - bool isBlinn() const; - void setBlinn(bool blinn); + void parseBlinnOnEvent(std::map &event); }; #endif //LEARNGLES_PHONGVSBLINNSCENE_H diff --git a/tutorial/src/main/cpp/lighting/ShadowScene.cpp b/tutorial/src/main/cpp/lighting/ShadowScene.cpp index 12a53b8a..d984c028 100644 --- a/tutorial/src/main/cpp/lighting/ShadowScene.cpp +++ b/tutorial/src/main/cpp/lighting/ShadowScene.cpp @@ -13,24 +13,25 @@ void ShadowScene::init() { // configure global opengl state // ----------------------------- glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); // build and compile shaders // ------------------------- - m_pShader = new Shader("3.1.3.shadow_mapping.vert", "shaders/shadow/3.1.3.shadow_mapping.frag"); - m_pSimpleDepthShader = new Shader("shaders/shadow3.1.3.shadow_mapping_depth.vert", "shaders/shadow/3.1.3.shadow_mapping_depth.frag"); - m_pDebugDepthQuad = new Shader("shaders/shadow/3.1.3.debug_quad.vert", "shaders/shadow/3.1.3.debug_quad_depth.frag"); + m_pShader = new Shader("shaders/shadow/shadow_mapping.vert", "shaders/shadow/shadow_mapping.frag"); + m_pSimpleDepthShader = new Shader("shaders/shadow/shadow_mapping_depth.vert", "shaders/shadow/shadow_mapping_depth.frag"); + m_pDebugDepthQuad = new Shader("shaders/shadow/debug_quad.vert", "shaders/shadow/debug_quad_depth.frag"); // set up vertex data (and buffer(s)) and configure vertex attributes // ------------------------------------------------------------------ float planeVertices[] = { // positions // normals // texcoords - 25.0f, -0.5f, 25.0f, 0.0f, 1.0f, 0.0f, 25.0f, 0.0f, -25.0f, -0.5f, 25.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, - -25.0f, -0.5f, -25.0f, 0.0f, 1.0f, 0.0f, 0.0f, 25.0f, + 25.0f, -0.5f, 25.0f, 0.0f, 1.0f, 0.0f, 25.0f, 0.0f, + 25.0f, -0.5f, -25.0f, 0.0f, 1.0f, 0.0f, 25.0f, 25.0f, - 25.0f, -0.5f, 25.0f, 0.0f, 1.0f, 0.0f, 25.0f, 0.0f, - -25.0f, -0.5f, -25.0f, 0.0f, 1.0f, 0.0f, 0.0f, 25.0f, - 25.0f, -0.5f, -25.0f, 0.0f, 1.0f, 0.0f, 25.0f, 25.0f + -25.0f, -0.5f, 25.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, + 25.0f, -0.5f, -25.0f, 0.0f, 1.0f, 0.0f, 25.0f, 25.0f, + -25.0f, -0.5f, -25.0f, 0.0f, 1.0f, 0.0f, 0.0f, 25.0f }; // plane VAO glGenVertexArrays(1, &m_planeVAO); @@ -56,18 +57,22 @@ void ShadowScene::init() { // create depth texture glGenTextures(1, &m_depthMap); glBindTexture(GL_TEXTURE_2D, m_depthMap); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - float borderColor[] = { 1.0, 1.0, 1.0, 1.0 }; - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // attach depth texture as FBO's depth buffer glBindFramebuffer(GL_FRAMEBUFFER, m_depthMapFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthMap, 0); - //glDrawBuffer(GL_NONE); //TODO Not support in GLSL + // glDrawBuffer(GL_NONE); //TODO Not support in GLSL + GLenum none = GL_NONE; + glDrawBuffers(1, &none); glReadBuffer(GL_NONE); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + LOGE("ShadowScene", "ERROR::FRAMEBUFFER:: Framebuffer is not complete!"); + glBindFramebuffer(GL_FRAMEBUFFER, 0); // shader configuration @@ -81,6 +86,8 @@ void ShadowScene::init() { void ShadowScene::resize(int width, int height) { m_camera->setAspec((float) width / (float) height); + m_width = width; + m_height = height; glViewport(0, 0, width, height); } @@ -111,7 +118,8 @@ void ShadowScene::draw() { } // reset viewport - glViewport(0, 0, 800, 600); + glViewport(0, 0, m_width, m_height); + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 2. render scene as normal using the generated depth/shadow map diff --git a/tutorial/src/main/cpp/lighting/ShadowScene.h b/tutorial/src/main/cpp/lighting/ShadowScene.h index 989efdad..8d0e7a74 100644 --- a/tutorial/src/main/cpp/lighting/ShadowScene.h +++ b/tutorial/src/main/cpp/lighting/ShadowScene.h @@ -40,6 +40,9 @@ public : unsigned int m_depthMapFBO = 0u; unsigned int m_depthMap = 0u; + int m_width = 0; + int m_height = 0; + void renderQuad(); void renderCube(); void renderScene(const Shader &shader); diff --git a/tutorial/src/main/cpp/lighting/SsaoScene.cpp b/tutorial/src/main/cpp/lighting/SsaoScene.cpp index 99ee3c01..a43ede5e 100644 --- a/tutorial/src/main/cpp/lighting/SsaoScene.cpp +++ b/tutorial/src/main/cpp/lighting/SsaoScene.cpp @@ -19,10 +19,10 @@ void SsaoScene::init() { // build and compile shaders // ------------------------- - m_pShaderGeometryPass = new Shader("shaders/ssao/9.ssao_geometry.vert", "shaders/ssao/9.ssao_geometry.frag"); - m_pShaderLightingPass = new Shader("shaders/ssao/9.ssao.vert", "shaders/ssao/9.ssao_lighting.frag"); - m_pShaderSSAO = new Shader("shaders/ssao/9.ssao.vert", "shaders/ssao/9.ssao.frag"); - m_pShaderSSAOBlur = new Shader("shaders/ssao/9.ssao.vert", "shaders/ssao/9.ssao_blur.frag"); + m_pShaderGeometryPass = new Shader("shaders/ssao/ssao_geometry.vert", "shaders/ssao/ssao_geometry.frag"); + m_pShaderLightingPass = new Shader("shaders/ssao/ssao.vert", "shaders/ssao/ssao_lighting.frag"); + m_pShaderSSAO = new Shader("shaders/ssao/ssao.vert", "shaders/ssao/ssao.frag"); + m_pShaderSSAOBlur = new Shader("shaders/ssao/ssao.vert", "shaders/ssao/ssao_blur.frag"); // load models // ----------- @@ -35,7 +35,7 @@ void SsaoScene::init() { // position color buffer glGenTextures(1, &m_gPosition); glBindTexture(GL_TEXTURE_2D, m_gPosition); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 800, 600, 0, GL_RGBA, GL_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -44,14 +44,14 @@ void SsaoScene::init() { // normal color buffer glGenTextures(1, &m_gNormal); glBindTexture(GL_TEXTURE_2D, m_gNormal); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 800, 600, 0, GL_RGBA, GL_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_gNormal, 0); // color + specular color buffer glGenTextures(1, &m_gAlbedo); glBindTexture(GL_TEXTURE_2D, m_gAlbedo); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 800, 600, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, m_gAlbedo, 0); @@ -61,7 +61,7 @@ void SsaoScene::init() { // create and attach depth buffer (renderbuffer) glGenRenderbuffers(1, &m_rboDepth); glBindRenderbuffer(GL_RENDERBUFFER, m_rboDepth); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 800, 600); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_WIDTH, SCR_HEIGHT); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_rboDepth); // finally check if framebuffer is complete if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) @@ -75,7 +75,7 @@ void SsaoScene::init() { // SSAO color buffer glGenTextures(1, &m_ssaoColorBuffer); glBindTexture(GL_TEXTURE_2D, m_ssaoColorBuffer); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 800, 600, 0, GL_RED, GL_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, SCR_WIDTH, SCR_HEIGHT, 0, GL_RED, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_ssaoColorBuffer, 0); @@ -85,7 +85,7 @@ void SsaoScene::init() { glBindFramebuffer(GL_FRAMEBUFFER, m_ssaoBlurFBO); glGenTextures(1, &m_ssaoColorBufferBlur); glBindTexture(GL_TEXTURE_2D, m_ssaoColorBufferBlur); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 800, 600, 0, GL_RED, GL_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, SCR_WIDTH, SCR_HEIGHT, 0, GL_RED, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_ssaoColorBufferBlur, 0); @@ -120,7 +120,7 @@ void SsaoScene::init() { } glGenTextures(1, &m_noiseTexture); glBindTexture(GL_TEXTURE_2D, m_noiseTexture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 4, 4, 0, GL_RGB, GL_FLOAT, &ssaoNoise[0]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 4, 4, 0, GL_RGB, GL_FLOAT, &ssaoNoise[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); @@ -142,6 +142,7 @@ void SsaoScene::init() { m_pShaderSSAO->setInt("gPosition", 0); m_pShaderSSAO->setInt("gNormal", 1); m_pShaderSSAO->setInt("texNoise", 2); + m_pShaderSSAO->setVec2("noiseScale", glm::vec2(SCR_WIDTH / 4.0f, SCR_HEIGHT / 4.0f)); } if(m_pShaderSSAOBlur) { @@ -153,6 +154,8 @@ void SsaoScene::init() { void SsaoScene::resize(int width, int height) { m_camera->setAspec((float) width / (float) height); glViewport(0, 0, width, height); + m_width = width; + m_height = height; } void SsaoScene::draw() { @@ -166,6 +169,7 @@ void SsaoScene::draw() { // ----------------------------------------------------------------- glBindFramebuffer(GL_FRAMEBUFFER, m_gBuffer); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); glm::mat4 projection = m_camera->getProjectionMatrix(); glm::mat4 view = m_camera->getViewMatrix(); glm::mat4 model = glm::mat4(1.0f); @@ -198,6 +202,7 @@ void SsaoScene::draw() { // ------------------------ glBindFramebuffer(GL_FRAMEBUFFER, m_ssaoFBO); glClear(GL_COLOR_BUFFER_BIT); + glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); if(m_pShaderSSAO) { m_pShaderSSAO->use(); @@ -220,6 +225,7 @@ void SsaoScene::draw() { // ------------------------------------ glBindFramebuffer(GL_FRAMEBUFFER, m_ssaoBlurFBO); glClear(GL_COLOR_BUFFER_BIT); + glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); if(m_pShaderSSAOBlur) { m_pShaderSSAOBlur->use(); @@ -233,6 +239,7 @@ void SsaoScene::draw() { // 4. lighting pass: traditional deferred Blinn-Phong lighting with added screen-space ambient occlusion // ----------------------------------------------------------------------------------------------------- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glViewport(0, 0, m_width, m_height); if(m_pShaderLightingPass) { m_pShaderLightingPass->use(); @@ -307,7 +314,6 @@ void SsaoScene::destroy() { } SsaoScene::~SsaoScene() { - } std::map SsaoScene::propertyEvent(std::map &map) { diff --git a/tutorial/src/main/cpp/lighting/SsaoScene.h b/tutorial/src/main/cpp/lighting/SsaoScene.h index d2c1ce43..a8075cc9 100644 --- a/tutorial/src/main/cpp/lighting/SsaoScene.h +++ b/tutorial/src/main/cpp/lighting/SsaoScene.h @@ -12,6 +12,9 @@ class Model; class SsaoScene : public TutorialScene { public : + static constexpr int SCR_WIDTH = 800; + static constexpr int SCR_HEIGHT = 600; + SsaoScene(); void init() override; @@ -52,9 +55,10 @@ public : unsigned int m_cubeVBO = 0u; unsigned int m_quadVAO = 0u; unsigned int m_quadVBO = 0u; + int m_width = 0, m_height = 0; - glm::vec3 m_lightPos; - glm::vec3 m_lightColor; + glm::vec3 m_lightPos = glm::vec3(2.0, 4.0, -2.0); + glm::vec3 m_lightColor = glm::vec3(0.7 , 0.2, 0.7); void parseTargetCameraEvent(std::map &event); }; diff --git a/tutorial/src/main/java/com/minininja/learngles/GLActivity.kt b/tutorial/src/main/java/com/minininja/learngles/GLActivity.kt index 6bc2239c..e1d1dac1 100644 --- a/tutorial/src/main/java/com/minininja/learngles/GLActivity.kt +++ b/tutorial/src/main/java/com/minininja/learngles/GLActivity.kt @@ -19,6 +19,7 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.displayCutoutPadding import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -37,9 +38,15 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Rect import androidx.compose.ui.graphics.Color +import androidx.compose.ui.input.pointer.PointerEventPass import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.layout.boundsInRoot +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import com.minininja.learngles.ui.theme.LearnGLESTheme @@ -117,7 +124,8 @@ fun Modifier.layer3DTouch(callback: Layer3DTouchCallback?): Modifier = this while (true) { val event = awaitPointerEvent() val changes = event.changes - val pressedChanges = changes.filter { it.pressed } + // Only process changes that haven't been consumed by layers above (like ControlPanel) + val pressedChanges = changes.filter { it.pressed && !it.isConsumed } val currentPointerCount = pressedChanges.size // --- MULTI-FINGER TAP DETECTION --- @@ -179,14 +187,19 @@ fun OpenGLContainer( overlay: @Composable () -> Unit = {} ) { var isExpanded by remember { mutableStateOf(true) } + var panelBounds by remember { mutableStateOf(Rect.Zero) } Box( - modifier = Modifier - .fillMaxSize() - .layer3DTouch(touchCallback) // Apply the callback here + modifier = Modifier.fillMaxSize() ) { - AndroidView( - factory = { context -> + // Camera Layer (Bottom) + Box( + modifier = Modifier + .fillMaxSize() + .layer3DTouch(touchCallback) + ) { + AndroidView( + factory = { context -> GLSurfaceView(context).apply { setEGLContextClientVersion(3) setEGLConfigChooser(8, 8, 8, 8, 16, 8) @@ -227,14 +240,39 @@ fun OpenGLContainer( }, modifier = Modifier.fillMaxSize() ) + } + + // Shield Layer (Middle) - Catch events on ControlPanel's background + if (panelBounds != Rect.Zero) { + val density = LocalDensity.current Box( modifier = Modifier - .displayCutoutPadding() - .padding(top = 8.dp, start = 8.dp) - .background(Color.Black.copy(alpha = 0.3f), RoundedCornerShape(8.dp)) - .padding(if (isExpanded) 4.dp else 8.dp) - .wrapContentSize() - ) { + .offset { IntOffset(panelBounds.left.toInt(), panelBounds.top.toInt()) } + .size( + width = with(density) { panelBounds.width.toDp() }, + height = with(density) { panelBounds.height.toDp() } + ) + .pointerInput(Unit) { + awaitPointerEventScope { + while (true) { + awaitPointerEvent().changes.forEach { it.consume() } + } + } + } + ) + } + + Box( + modifier = Modifier + .onGloballyPositioned { coordinates -> + panelBounds = coordinates.boundsInRoot() + } + .displayCutoutPadding() + .padding(top = 8.dp, start = 8.dp) + .background(Color.Black.copy(alpha = 0.3f), RoundedCornerShape(8.dp)) + .padding(if (isExpanded) 4.dp else 8.dp) + .wrapContentSize() + ) { Column(modifier = Modifier.width(IntrinsicSize.Max)) { if (!isExpanded) { Icon( diff --git a/tutorial/src/main/java/com/minininja/learngles/lighting/BasicLightingActivity.kt b/tutorial/src/main/java/com/minininja/learngles/lighting/BasicLightingActivity.kt index bf97b26f..7dc97f55 100644 --- a/tutorial/src/main/java/com/minininja/learngles/lighting/BasicLightingActivity.kt +++ b/tutorial/src/main/java/com/minininja/learngles/lighting/BasicLightingActivity.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.material3.Checkbox +import androidx.compose.material3.Slider import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -16,13 +17,19 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp +import androidx.compose.ui.tooling.preview.Preview import com.minininja.learngles.GLActivity import com.minininja.learngles.Layer3DTouchCallback import com.minininja.learngles.NativeHelper +import com.minininja.learngles.ui.theme.LearnGLESTheme class BasicLightingActivity : GLActivity() { private var active by mutableStateOf(true) + private var ambientFactor by mutableStateOf(0.35f) + private var diffuseFactor by mutableStateOf(0.5f) + private var specularFactor by mutableStateOf(1.0f) + override fun createTouchCallback(): Layer3DTouchCallback { return object : Layer3DTouchCallback { @@ -85,26 +92,95 @@ class BasicLightingActivity : GLActivity() { onActiveChange = { active = it }, + ambientFactor = ambientFactor, + onAmbientFactorChange = { + Log.i(TAG, "onAmbientFactorChange [curr $it ] <=> [prev $ambientFactor]") + ambientFactor = it + updateProperty("ambientFactor", it) + }, + diffuseFactor = diffuseFactor, + onDiffuseFactorChange = { + diffuseFactor = it + updateProperty("diffuseFactor", it) + }, + specularFactor = specularFactor, + onSpecularFactorChange = { + specularFactor = it + updateProperty("specularFactor", it) + } ) } + + private fun updateProperty(name: String, value: Float) { + val event = mapOf(name to value) + NativeHelper.sendCommands(event) + glSurfaceView?.requestRender() + } + + companion object { + private const val TAG = "BasicLightingActivity" + } } @Composable private fun ControlPanelContent( active: Boolean, onActiveChange: (Boolean) -> Unit, + ambientFactor: Float, + onAmbientFactorChange: (Float) -> Unit, + diffuseFactor: Float, + onDiffuseFactorChange: (Float) -> Unit, + specularFactor: Float, + onSpecularFactorChange: (Float) -> Unit, modifier: Modifier = Modifier, ) { Column( - modifier = modifier.wrapContentSize() + modifier = modifier.wrapContentSize().padding(8.dp) ) { - Row(verticalAlignment = Alignment.CenterVertically, - modifier = modifier.padding(8.dp)) { + Row(verticalAlignment = Alignment.CenterVertically) { Text(text = "Target Camera Events", color = Color.White) Checkbox( checked = active, onCheckedChange = onActiveChange ) } + + FactorSlider(label = "Ambient Factor", value = ambientFactor, onValueChange = onAmbientFactorChange) + FactorSlider(label = "Diffuse Factor", value = diffuseFactor, onValueChange = onDiffuseFactorChange) + FactorSlider(label = "Specular Factor", value = specularFactor, onValueChange = onSpecularFactorChange) + } +} + +@Composable +private fun FactorSlider( + label: String, + value: Float, + onValueChange: (Float) -> Unit, + modifier: Modifier = Modifier +) { + Column(modifier = modifier.padding(vertical = 4.dp)) { + Text(text = "$label: ${"%.2f".format(value)}", color = Color.White) + Slider( + value = value, + onValueChange = onValueChange, + valueRange = 0f..1f + ) + } +} + +@Preview(showBackground = true, backgroundColor = 0xFF000000) +@Composable +private fun ControlPanelPreview() { + LearnGLESTheme { + ControlPanelContent( + active = true, + onActiveChange = {}, + ambientFactor = 0.35f, + onAmbientFactorChange = {}, + diffuseFactor = 0.5f, + onDiffuseFactorChange = {}, + specularFactor = 1.0f, + onSpecularFactorChange = {} + ) } } diff --git a/tutorial/src/main/java/com/minininja/learngles/lighting/HdrActivity.kt b/tutorial/src/main/java/com/minininja/learngles/lighting/HdrActivity.kt index 01e51f91..ab979f22 100644 --- a/tutorial/src/main/java/com/minininja/learngles/lighting/HdrActivity.kt +++ b/tutorial/src/main/java/com/minininja/learngles/lighting/HdrActivity.kt @@ -64,6 +64,7 @@ class HdrActivity : GLActivity() { val event = mapOf("event_id" to "target_camera_touching_event", "reset" to 1) NativeHelper.sendCommands(event) + glSurfaceView?.requestRender() Log.d("HdrActivity", "Custom DoubleClick at: $event") } diff --git a/tutorial/src/main/java/com/minininja/learngles/lighting/LightCasterActivity.kt b/tutorial/src/main/java/com/minininja/learngles/lighting/LightCasterActivity.kt index ae8bb27c..80076fd6 100644 --- a/tutorial/src/main/java/com/minininja/learngles/lighting/LightCasterActivity.kt +++ b/tutorial/src/main/java/com/minininja/learngles/lighting/LightCasterActivity.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.material3.Checkbox +import androidx.compose.material3.Slider import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -16,13 +17,19 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp +import androidx.compose.ui.tooling.preview.Preview import com.minininja.learngles.GLActivity import com.minininja.learngles.Layer3DTouchCallback import com.minininja.learngles.NativeHelper +import com.minininja.learngles.ui.theme.LearnGLESTheme class LightCasterActivity : GLActivity() { private var active by mutableStateOf(true) + private var ambientFactor by mutableStateOf(0.35f) + private var diffuseFactor by mutableStateOf(0.5f) + private var specularFactor by mutableStateOf(1.0f) + override fun createTouchCallback(): Layer3DTouchCallback { return object : Layer3DTouchCallback { @@ -85,26 +92,90 @@ class LightCasterActivity : GLActivity() { onActiveChange = { active = it }, + ambientFactor = ambientFactor, + onAmbientFactorChange = { + ambientFactor = it + updateProperty("ambientFactor", it) + }, + diffuseFactor = diffuseFactor, + onDiffuseFactorChange = { + diffuseFactor = it + updateProperty("diffuseFactor", it) + }, + specularFactor = specularFactor, + onSpecularFactorChange = { + specularFactor = it + updateProperty("specularFactor", it) + } ) } + + private fun updateProperty(name: String, value: Float) { + val event = mapOf(name to value) + NativeHelper.sendCommands(event) + glSurfaceView?.requestRender() + } } @Composable private fun ControlPanelContent( active: Boolean, onActiveChange: (Boolean) -> Unit, + ambientFactor: Float, + onAmbientFactorChange: (Float) -> Unit, + diffuseFactor: Float, + onDiffuseFactorChange: (Float) -> Unit, + specularFactor: Float, + onSpecularFactorChange: (Float) -> Unit, modifier: Modifier = Modifier, ) { Column( - modifier = modifier.wrapContentSize() + modifier = modifier.wrapContentSize().padding(8.dp) ) { - Row(verticalAlignment = Alignment.CenterVertically, - modifier = modifier.padding(8.dp)) { + Row(verticalAlignment = Alignment.CenterVertically) { Text(text = "Target Camera Events", color = Color.White) Checkbox( checked = active, onCheckedChange = onActiveChange ) } + + FactorSlider(label = "Ambient Factor", value = ambientFactor, onValueChange = onAmbientFactorChange) + FactorSlider(label = "Diffuse Factor", value = diffuseFactor, onValueChange = onDiffuseFactorChange) + FactorSlider(label = "Specular Factor", value = specularFactor, onValueChange = onSpecularFactorChange) + } +} + +@Composable +private fun FactorSlider( + label: String, + value: Float, + onValueChange: (Float) -> Unit, + modifier: Modifier = Modifier +) { + Column(modifier = modifier.padding(vertical = 4.dp)) { + Text(text = "$label: ${"%.2f".format(value)}", color = Color.White) + Slider( + value = value, + onValueChange = onValueChange, + valueRange = 0f..1f + ) + } +} + +@Preview(showBackground = true, backgroundColor = 0xFF000000) +@Composable +private fun ControlPanelPreview() { + LearnGLESTheme { + ControlPanelContent( + active = true, + onActiveChange = {}, + ambientFactor = 0.35f, + onAmbientFactorChange = {}, + diffuseFactor = 0.5f, + onDiffuseFactorChange = {}, + specularFactor = 1.0f, + onSpecularFactorChange = {} + ) } } diff --git a/tutorial/src/main/java/com/minininja/learngles/lighting/PhongVsBlinnActivity.kt b/tutorial/src/main/java/com/minininja/learngles/lighting/PhongVsBlinnActivity.kt index c59ba510..ed061457 100644 --- a/tutorial/src/main/java/com/minininja/learngles/lighting/PhongVsBlinnActivity.kt +++ b/tutorial/src/main/java/com/minininja/learngles/lighting/PhongVsBlinnActivity.kt @@ -23,6 +23,8 @@ import com.minininja.learngles.NativeHelper class PhongVsBlinnActivity : GLActivity() { private var active by mutableStateOf(true) + private var blinnOn by mutableStateOf(true) + override fun createTouchCallback(): Layer3DTouchCallback { return object : Layer3DTouchCallback { @@ -64,6 +66,7 @@ class PhongVsBlinnActivity : GLActivity() { val event = mapOf("event_id" to "target_camera_touching_event", "reset" to 1) NativeHelper.sendCommands(event) + glSurfaceView?.requestRender() Log.d("PhongVsBlinnActivity", "Custom DoubleClick at: $event") } @@ -81,16 +84,31 @@ class PhongVsBlinnActivity : GLActivity() { @Composable override fun ControlPanel() { ControlPanelContent( + title = "Target Camera Events", active = active, onActiveChange = { active = it }, ) + + ControlPanelContent( + title = "Blinn On", + active = blinnOn, + onActiveChange = { + blinnOn = it + val event = mapOf("event_id" to "blinn_on_event", "on" to it) + glSurfaceView?.queueEvent { + NativeHelper.sendCommands(event) + glSurfaceView?.requestRender() + } + }, + ) } } @Composable private fun ControlPanelContent( + title: String, active: Boolean, onActiveChange: (Boolean) -> Unit, modifier: Modifier = Modifier, @@ -100,7 +118,7 @@ private fun ControlPanelContent( ) { Row(verticalAlignment = Alignment.CenterVertically, modifier = modifier.padding(8.dp)) { - Text(text = "Target Camera Events", color = Color.White) + Text(text = title, color = Color.White) Checkbox( checked = active, onCheckedChange = onActiveChange diff --git a/tutorial/src/main/java/com/minininja/learngles/ui/SimplexTriangleEditor.kt b/tutorial/src/main/java/com/minininja/learngles/ui/SimplexTriangleEditor.kt new file mode 100644 index 00000000..43b72a2f --- /dev/null +++ b/tutorial/src/main/java/com/minininja/learngles/ui/SimplexTriangleEditor.kt @@ -0,0 +1,157 @@ +package com.minininja.learngles.ui + +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.gestures.detectDragGestures +import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Path +import androidx.compose.ui.graphics.drawscope.Stroke +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.tooling.preview.Preview +import com.minininja.learngles.ui.theme.LearnGLESTheme +import kotlin.math.max +import kotlin.math.min +import kotlin.math.sqrt + +// Data class to hold our normalized weights +data class SimplexWeights(val a: Float, val b: Float, val c: Float) + +@Composable +fun SimplexTriangleEditor( + modifier: Modifier = Modifier, + initialWeights: SimplexWeights = SimplexWeights(0.333f, 0.333f, 0.334f), + onWeightsChanged: (SimplexWeights) -> Unit +) { + var weights by remember { mutableStateOf(initialWeights) } + + Box(modifier = modifier) { + Canvas( + modifier = Modifier + .fillMaxSize() + .pointerInput(Unit) { + // Handle dragging the handle + detectDragGestures { change, _ -> + change.consume() + val newWeights = calculateWeightsFromScreenPos( + pointerPos = change.position, + canvasWidth = size.width.toFloat(), + canvasHeight = size.height.toFloat() + ) + weights = newWeights + onWeightsChanged(newWeights) + } + } + .pointerInput(Unit) { + // Handle snapping to a direct tap location + detectTapGestures { offset -> + val newWeights = calculateWeightsFromScreenPos( + pointerPos = offset, + canvasWidth = size.width.toFloat(), + canvasHeight = size.height.toFloat() + ) + weights = newWeights + onWeightsChanged(newWeights) + } + } + ) { + // 1. Calculate Geometry Layout dynamically based on Canvas boundaries + val centerX = size.width / 2f + val centerY = size.height / 2f + // Use 85% of the shortest dimension as the bounding radius to ensure padding + val radius = min(size.width, size.height) * 0.425f + + val sqrt3Over2 = sqrt(3f) / 2f + + val vertA = Offset(centerX, centerY - radius) + val vertB = Offset(centerX - radius * sqrt3Over2, centerY + radius * 0.5f) + val vertC = Offset(centerX + radius * sqrt3Over2, centerY + radius * 0.5f) + + // 2. Draw the Equilateral Triangle Hull + val trianglePath = Path().apply { + moveTo(vertA.x, vertA.y) + lineTo(vertB.x, vertB.y) + lineTo(vertC.x, vertC.y) + close() + } + drawPath(path = trianglePath, color = Color.Gray, style = Stroke(width = 4f)) + + // Draw distinct corner nodes for visual reference + drawCircle(color = Color.Red, radius = 12f, center = vertA) // Vertex A + drawCircle(color = Color.Green, radius = 12f, center = vertB) // Vertex B + drawCircle(color = Color.Blue, radius = 12f, center = vertC) // Vertex C + + // 3. Compute Current 2D Handle Location from Weights (Forward Kinematics) + val handleX = weights.a * vertA.x + weights.b * vertB.x + weights.c * vertC.x + val handleY = weights.a * vertA.y + weights.b * vertB.y + weights.c * vertC.y + + // 4. Draw Interactive Selector Handle + drawCircle( + color = Color.DarkGray, + radius = 24f, + center = Offset(handleX, handleY), + style = Stroke(width = 6f) + ) + drawCircle( + color = Color.White, + radius = 20f, + center = Offset(handleX, handleY) + ) + } + } +} + +// Inverse Kinematics: Maps pixel offsets directly into normalized weights +private fun calculateWeightsFromScreenPos( + pointerPos: Offset, + canvasWidth: Float, + canvasHeight: Float +): SimplexWeights { + val centerX = canvasWidth / 2f + val centerY = canvasHeight / 2f + val radius = min(canvasWidth, canvasHeight) * 0.425f + val sqrt3Over2 = sqrt(3f) / 2f + + val ax = centerX + val ay = centerY - radius + val bx = centerX - radius * sqrt3Over2 + val by = centerY + radius * 0.5f + val cx = centerX + radius * sqrt3Over2 + val cy = centerY + radius * 0.5f + + // Determinant of the barycentric transformation matrix + val delta = (by - cy) * (ax - cx) + (cx - bx) * (ay - cy) + + // Compute raw weights using area cross products + var rawA = ((by - cy) * (pointerPos.x - cx) + (cx - bx) * (pointerPos.y - cy)) / delta + var rawB = ((cy - ay) * (pointerPos.x - cx) + (ax - cx) * (pointerPos.y - cy)) / delta + + // Clamp values inside [0.0, 1.0] boundaries + rawA = max(0f, min(1f, rawA)) + rawB = max(0f, min(1f, rawB)) + var rawC = max(0f, min(1f, 1f - rawA - rawB)) + + // Re-normalize weight vectors to eliminate tracking precision loss outside bounds + val sum = rawA + rawB + rawC + return if (sum > 0f) { + SimplexWeights(rawA / sum, rawB / sum, rawC / sum) + } else { + SimplexWeights(0.333f, 0.333f, 0.334f) + } +} + +@Preview(showBackground = true) +@Composable +fun SimplexTriangleEditorPreview() { + LearnGLESTheme { + SimplexTriangleEditor( + modifier = Modifier.fillMaxSize(), + initialWeights = SimplexWeights(0.333f, 0.333f, 0.334f), + onWeightsChanged = {} + ) + } +}