Skybox stuff.
@ -24,7 +24,7 @@ struct SubMesh {
|
|||||||
float shininess;
|
float shininess;
|
||||||
GLuint diffuseTexture;
|
GLuint diffuseTexture;
|
||||||
// (Optional) If you add a normal texture per submesh.
|
// (Optional) If you add a normal texture per submesh.
|
||||||
// GLuint normalTexture;
|
GLuint normalTexture;
|
||||||
GLuint VAO, VBO, EBO;
|
GLuint VAO, VBO, EBO;
|
||||||
|
|
||||||
SubMesh()
|
SubMesh()
|
||||||
|
@ -52,12 +52,19 @@ private:
|
|||||||
static GLuint depthRenderbuffer;
|
static GLuint depthRenderbuffer;
|
||||||
// Shader program used for rendering the scene.
|
// Shader program used for rendering the scene.
|
||||||
static GLuint shaderProgram;
|
static GLuint shaderProgram;
|
||||||
|
|
||||||
|
static GLuint skyboxShaderProgram;
|
||||||
|
static GLuint skyboxVAO, skyboxVBO, skyboxEBO;
|
||||||
|
static GLuint skyboxCubemap;
|
||||||
|
|
||||||
// Rotation angle (if needed for animated models).
|
// Rotation angle (if needed for animated models).
|
||||||
static float rotationAngle;
|
static float rotationAngle;
|
||||||
// Current offscreen framebuffer dimensions.
|
// Current offscreen framebuffer dimensions.
|
||||||
static int fbWidth;
|
static int fbWidth;
|
||||||
static int fbHeight;
|
static int fbHeight;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Helper function to compile and link shaders.
|
// Helper function to compile and link shaders.
|
||||||
static GLuint CompileShader(const char* vertexSrc, const char* fragmentSrc);
|
static GLuint CompileShader(const char* vertexSrc, const char* fragmentSrc);
|
||||||
// Sets up common scene resources (e.g. loading the scene shader).
|
// Sets up common scene resources (e.g. loading the scene shader).
|
||||||
|
@ -11,6 +11,13 @@ GLuint Engine::framebuffer = 0;
|
|||||||
GLuint Engine::colorTexture = 0;
|
GLuint Engine::colorTexture = 0;
|
||||||
GLuint Engine::depthRenderbuffer = 0;
|
GLuint Engine::depthRenderbuffer = 0;
|
||||||
GLuint Engine::shaderProgram = 0;
|
GLuint Engine::shaderProgram = 0;
|
||||||
|
|
||||||
|
GLuint Engine::skyboxShaderProgram = 0;
|
||||||
|
GLuint Engine::skyboxVAO = 0;
|
||||||
|
GLuint Engine::skyboxVBO = 0;
|
||||||
|
GLuint Engine::skyboxEBO = 0;
|
||||||
|
GLuint Engine::skyboxCubemap = 0;
|
||||||
|
|
||||||
float Engine::rotationAngle = 0.0f;
|
float Engine::rotationAngle = 0.0f;
|
||||||
int Engine::fbWidth = 640;
|
int Engine::fbWidth = 640;
|
||||||
int Engine::fbHeight = 400;
|
int Engine::fbHeight = 400;
|
||||||
@ -18,6 +25,64 @@ int Engine::fbHeight = 400;
|
|||||||
// Global normal map texture (if needed for legacy models; otherwise each model handles its own)
|
// Global normal map texture (if needed for legacy models; otherwise each model handles its own)
|
||||||
GLuint normalMapTexture = 0;
|
GLuint normalMapTexture = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int loadCubemap(const std::vector<std::string>& faces)
|
||||||
|
{
|
||||||
|
unsigned int textureID;
|
||||||
|
glGenTextures(1, &textureID);
|
||||||
|
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
|
||||||
|
|
||||||
|
// Disable vertical flipping for cubemaps.
|
||||||
|
stbi_set_flip_vertically_on_load(false);
|
||||||
|
|
||||||
|
int width, height, nrChannels;
|
||||||
|
for (unsigned int i = 0; i < faces.size(); i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::cout << "Loading Cubemap: " << faces[i] << std::endl;
|
||||||
|
unsigned char *data = stbi_load(faces[i].c_str(), &width, &height, &nrChannels, 0);
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
GLenum format = GL_RGB;
|
||||||
|
if(nrChannels == 1)
|
||||||
|
format = GL_RED;
|
||||||
|
else if(nrChannels == 3)
|
||||||
|
format = GL_RGB;
|
||||||
|
else if(nrChannels == 4)
|
||||||
|
format = GL_RGBA;
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
|
||||||
|
0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
|
||||||
|
stbi_image_free(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Cubemap texture failed to load at path: " << faces[i] << std::endl;
|
||||||
|
stbi_image_free(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set texture parameters
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
return textureID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Engine::Init()
|
bool Engine::Init()
|
||||||
{
|
{
|
||||||
if (!glfwInit())
|
if (!glfwInit())
|
||||||
@ -172,12 +237,9 @@ GLuint Engine::CompileShader(const char *vertexSrc, const char *fragmentSrc)
|
|||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetupScene now creates the shader program used for all models.
|
|
||||||
// It no longer creates cube-specific VAOs, since ModelComponent will store mesh data.
|
|
||||||
bool Engine::SetupScene()
|
bool Engine::SetupScene()
|
||||||
{
|
{
|
||||||
|
// --- Scene Shader Program ---
|
||||||
// Vertex Shader remains largely unchanged.
|
|
||||||
const char *vertexShaderSrc = R"(
|
const char *vertexShaderSrc = R"(
|
||||||
#version 330 core
|
#version 330 core
|
||||||
layout(location = 0) in vec3 aPos;
|
layout(location = 0) in vec3 aPos;
|
||||||
@ -201,10 +263,9 @@ bool Engine::SetupScene()
|
|||||||
Tangent = mat3(model) * aTangent;
|
Tangent = mat3(model) * aTangent;
|
||||||
gl_Position = projection * view * vec4(FragPos, 1.0);
|
gl_Position = projection * view * vec4(FragPos, 1.0);
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
// Fragment Shader with support for optional diffuse and normal maps and using Blinn-Phong lighting.
|
const char *fragmentShaderSrc = R"(
|
||||||
const char* fragmentShaderSrc = R"(
|
|
||||||
#version 330 core
|
#version 330 core
|
||||||
out vec4 FragColor;
|
out vec4 FragColor;
|
||||||
|
|
||||||
@ -222,7 +283,10 @@ const char* fragmentShaderSrc = R"(
|
|||||||
uniform sampler2D diffuseTexture;
|
uniform sampler2D diffuseTexture;
|
||||||
uniform sampler2D normalMap;
|
uniform sampler2D normalMap;
|
||||||
uniform bool useDiffuseTexture;
|
uniform bool useDiffuseTexture;
|
||||||
uniform bool useNormalMap; // Control flag for normal mapping
|
uniform bool useNormalMap;
|
||||||
|
|
||||||
|
// Skybox cubemap for ambient lighting.
|
||||||
|
uniform samplerCube skybox;
|
||||||
|
|
||||||
// Material properties.
|
// Material properties.
|
||||||
uniform vec3 materialDiffuse;
|
uniform vec3 materialDiffuse;
|
||||||
@ -233,35 +297,31 @@ const char* fragmentShaderSrc = R"(
|
|||||||
// Optionally sample the diffuse texture.
|
// Optionally sample the diffuse texture.
|
||||||
vec3 diffuseTex = useDiffuseTexture ? texture(diffuseTexture, TexCoords).rgb : vec3(1.0);
|
vec3 diffuseTex = useDiffuseTexture ? texture(diffuseTexture, TexCoords).rgb : vec3(1.0);
|
||||||
|
|
||||||
// Determine the normal.
|
// Determine the final normal.
|
||||||
vec3 finalNormal;
|
vec3 finalNormal;
|
||||||
if(useNormalMap) {
|
if(useNormalMap) {
|
||||||
// Sample the normal map and convert from [0,1] to [-1,1].
|
|
||||||
vec3 normMap = texture(normalMap, TexCoords).rgb;
|
vec3 normMap = texture(normalMap, TexCoords).rgb;
|
||||||
normMap = normalize(normMap * 2.0 - 1.0);
|
normMap = normalize(normMap * 2.0 - 1.0);
|
||||||
// (The z-flip here depends on your texture convention.)
|
|
||||||
normMap.z = -normMap.z;
|
normMap.z = -normMap.z;
|
||||||
vec3 T = normalize(Tangent);
|
vec3 T = normalize(Tangent);
|
||||||
vec3 B = normalize(cross(Normal, T));
|
vec3 B = normalize(cross(Normal, T));
|
||||||
mat3 TBN = mat3(T, B, normalize(Normal));
|
mat3 TBN = mat3(T, B, normalize(Normal));
|
||||||
finalNormal = normalize(TBN * normMap);
|
finalNormal = normalize(TBN * normMap);
|
||||||
} else {
|
} else {
|
||||||
// Use the interpolated vertex normal if no normal map is provided.
|
|
||||||
finalNormal = normalize(Normal);
|
finalNormal = normalize(Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start with an ambient term.
|
// Sample ambient from the skybox cubemap.
|
||||||
vec3 ambient = 0.1 * materialDiffuse * diffuseTex;
|
vec3 ambient = texture(skybox, finalNormal).rgb * 0.1 * materialDiffuse;
|
||||||
|
|
||||||
vec3 lighting = ambient;
|
vec3 lighting = ambient;
|
||||||
|
|
||||||
// Loop through each light.
|
// Loop through lights.
|
||||||
for(int i = 0; i < numLights; i++) {
|
for(int i = 0; i < numLights; i++) {
|
||||||
vec3 lightDir = normalize(lightPositions[i] - FragPos);
|
vec3 lightDir = normalize(lightPositions[i] - FragPos);
|
||||||
// Diffuse term.
|
|
||||||
float diff = max(dot(finalNormal, lightDir), 0.0);
|
float diff = max(dot(finalNormal, lightDir), 0.0);
|
||||||
vec3 diffuse = diff * materialDiffuse * diffuseTex * lightColors[i];
|
vec3 diffuse = diff * materialDiffuse * diffuseTex * lightColors[i];
|
||||||
|
|
||||||
// Blinn-Phong Specular term.
|
|
||||||
vec3 viewDir = normalize(viewPos - FragPos);
|
vec3 viewDir = normalize(viewPos - FragPos);
|
||||||
vec3 halfDir = normalize(lightDir + viewDir);
|
vec3 halfDir = normalize(lightDir + viewDir);
|
||||||
float spec = pow(max(dot(finalNormal, halfDir), 0.0), materialShininess);
|
float spec = pow(max(dot(finalNormal, halfDir), 0.0), materialShininess);
|
||||||
@ -272,8 +332,7 @@ const char* fragmentShaderSrc = R"(
|
|||||||
|
|
||||||
FragColor = vec4(lighting, 1.0);
|
FragColor = vec4(lighting, 1.0);
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
|
|
||||||
shaderProgram = CompileShader(vertexShaderSrc, fragmentShaderSrc);
|
shaderProgram = CompileShader(vertexShaderSrc, fragmentShaderSrc);
|
||||||
if (shaderProgram == 0)
|
if (shaderProgram == 0)
|
||||||
@ -281,74 +340,189 @@ const char* fragmentShaderSrc = R"(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Skybox Shader Program ---
|
||||||
|
const char *skyboxVertexShaderSrc = R"(
|
||||||
|
#version 330 core
|
||||||
|
layout(location = 0) in vec3 aPos;
|
||||||
|
out vec3 TexCoords;
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 projection;
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
TexCoords = aPos;
|
||||||
|
// Remove translation by setting w equal to z component.
|
||||||
|
vec4 pos = projection * view * vec4(aPos, 1.0);
|
||||||
|
gl_Position = pos.xyww;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
const char *skyboxFragmentShaderSrc = R"(
|
||||||
|
#version 330 core
|
||||||
|
in vec3 TexCoords;
|
||||||
|
out vec4 FragColor;
|
||||||
|
uniform samplerCube skybox;
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = texture(skybox, TexCoords);
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
skyboxShaderProgram = CompileShader(skyboxVertexShaderSrc, skyboxFragmentShaderSrc);
|
||||||
|
if (skyboxShaderProgram == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define the full cube (36 vertices) for the skybox.
|
||||||
|
float skyboxVertices[] = {
|
||||||
|
// positions
|
||||||
|
-1.0f, 1.0f, -1.0f,
|
||||||
|
-1.0f, -1.0f, -1.0f,
|
||||||
|
1.0f, -1.0f, -1.0f,
|
||||||
|
1.0f, -1.0f, -1.0f,
|
||||||
|
1.0f, 1.0f, -1.0f,
|
||||||
|
-1.0f, 1.0f, -1.0f,
|
||||||
|
|
||||||
|
-1.0f, -1.0f, 1.0f,
|
||||||
|
-1.0f, -1.0f, -1.0f,
|
||||||
|
-1.0f, 1.0f, -1.0f,
|
||||||
|
-1.0f, 1.0f, -1.0f,
|
||||||
|
-1.0f, 1.0f, 1.0f,
|
||||||
|
-1.0f, -1.0f, 1.0f,
|
||||||
|
|
||||||
|
1.0f, -1.0f, -1.0f,
|
||||||
|
1.0f, -1.0f, 1.0f,
|
||||||
|
1.0f, 1.0f, 1.0f,
|
||||||
|
1.0f, 1.0f, 1.0f,
|
||||||
|
1.0f, 1.0f, -1.0f,
|
||||||
|
1.0f, -1.0f, -1.0f,
|
||||||
|
|
||||||
|
-1.0f, -1.0f, 1.0f,
|
||||||
|
-1.0f, 1.0f, 1.0f,
|
||||||
|
1.0f, 1.0f, 1.0f,
|
||||||
|
1.0f, 1.0f, 1.0f,
|
||||||
|
1.0f, -1.0f, 1.0f,
|
||||||
|
-1.0f, -1.0f, 1.0f,
|
||||||
|
|
||||||
|
-1.0f, 1.0f, -1.0f,
|
||||||
|
1.0f, 1.0f, -1.0f,
|
||||||
|
1.0f, 1.0f, 1.0f,
|
||||||
|
1.0f, 1.0f, 1.0f,
|
||||||
|
-1.0f, 1.0f, 1.0f,
|
||||||
|
-1.0f, 1.0f, -1.0f,
|
||||||
|
|
||||||
|
-1.0f, -1.0f, -1.0f,
|
||||||
|
-1.0f, -1.0f, 1.0f,
|
||||||
|
1.0f, -1.0f, -1.0f,
|
||||||
|
1.0f, -1.0f, -1.0f,
|
||||||
|
-1.0f, -1.0f, 1.0f,
|
||||||
|
1.0f, -1.0f, 1.0f};
|
||||||
|
|
||||||
|
unsigned int skyboxVAO, skyboxVBO;
|
||||||
|
glGenVertexArrays(1, &skyboxVAO);
|
||||||
|
glGenBuffers(1, &skyboxVBO);
|
||||||
|
glBindVertexArray(skyboxVAO);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), skyboxVertices, GL_STATIC_DRAW);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
|
||||||
|
std::vector<std::string> faces{
|
||||||
|
"assets/skybox/right.jpg",
|
||||||
|
"assets/skybox/left.jpg",
|
||||||
|
"assets/skybox/top.jpg",
|
||||||
|
"assets/skybox/bottom.jpg",
|
||||||
|
"assets/skybox/front.jpg",
|
||||||
|
"assets/skybox/back.jpg"
|
||||||
|
};
|
||||||
|
skyboxCubemap = loadCubemap(faces);
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImTextureID Engine::RenderScene(const glm::mat4 &view, const glm::mat4 &projection, const glm::vec3 &viewPos, const std::vector<Entity*>& entities) {
|
ImTextureID Engine::RenderScene(const glm::mat4 &view, const glm::mat4 &projection,
|
||||||
|
const glm::vec3 &viewPos, const std::vector<Entity *> &entities)
|
||||||
|
{
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||||
glViewport(0, 0, fbWidth, fbHeight);
|
glViewport(0, 0, fbWidth, fbHeight);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
// --- Draw Scene Objects ---
|
||||||
glUseProgram(shaderProgram);
|
glUseProgram(shaderProgram);
|
||||||
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||||
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||||
glUniform3f(glGetUniformLocation(shaderProgram, "viewPos"), viewPos.x, viewPos.y, viewPos.z);
|
glUniform3f(glGetUniformLocation(shaderProgram, "viewPos"), viewPos.x, viewPos.y, viewPos.z);
|
||||||
|
|
||||||
// Gather up to 2 lights.
|
// Bind skybox cubemap for ambient sampling in the scene shader.
|
||||||
glm::vec3 lightPositions[2] = { glm::vec3(0.0f), glm::vec3(0.0f) };
|
glActiveTexture(GL_TEXTURE2);
|
||||||
glm::vec3 lightColors[2] = { glm::vec3(1.0f), glm::vec3(1.0f) };
|
glBindTexture(GL_TEXTURE_CUBE_MAP, skyboxCubemap);
|
||||||
|
glUniform1i(glGetUniformLocation(shaderProgram, "skybox"), 2);
|
||||||
|
|
||||||
|
// Set up lights (up to 2).
|
||||||
|
glm::vec3 lightPositions[2] = {glm::vec3(0.0f), glm::vec3(0.0f)};
|
||||||
|
glm::vec3 lightColors[2] = {glm::vec3(1.0f), glm::vec3(1.0f)};
|
||||||
int lightCount = 0;
|
int lightCount = 0;
|
||||||
for (auto e : entities) {
|
for (auto e : entities)
|
||||||
if (e->GetType() == EntityType::LIGHT && lightCount < 2) {
|
{
|
||||||
|
if (e->GetType() == EntityType::LIGHT && lightCount < 2)
|
||||||
|
{
|
||||||
lightPositions[lightCount] = e->transform.position;
|
lightPositions[lightCount] = e->transform.position;
|
||||||
if (e->lightComponent) {
|
if (e->lightComponent)
|
||||||
|
{
|
||||||
lightColors[lightCount] = e->lightComponent->color * e->lightComponent->intensity;
|
lightColors[lightCount] = e->lightComponent->color * e->lightComponent->intensity;
|
||||||
}
|
}
|
||||||
lightCount++;
|
lightCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
glUniform1i(glGetUniformLocation(shaderProgram, "numLights"), lightCount);
|
glUniform1i(glGetUniformLocation(shaderProgram, "numLights"), lightCount);
|
||||||
if (lightCount > 0) {
|
if (lightCount > 0)
|
||||||
|
{
|
||||||
glUniform3fv(glGetUniformLocation(shaderProgram, "lightPositions"), lightCount, glm::value_ptr(lightPositions[0]));
|
glUniform3fv(glGetUniformLocation(shaderProgram, "lightPositions"), lightCount, glm::value_ptr(lightPositions[0]));
|
||||||
glUniform3fv(glGetUniformLocation(shaderProgram, "lightColors"), lightCount, glm::value_ptr(lightColors[0]));
|
glUniform3fv(glGetUniformLocation(shaderProgram, "lightColors"), lightCount, glm::value_ptr(lightColors[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render each cube entity using its ModelComponent.
|
// Render each cube entity using its ModelComponent.
|
||||||
for (auto e : entities) {
|
for (auto e : entities)
|
||||||
if (e->GetType() == EntityType::CUBE && e->modelComponent) {
|
{
|
||||||
|
if (e->GetType() == EntityType::CUBE && e->modelComponent)
|
||||||
|
{
|
||||||
glm::mat4 modelMatrix = e->transform.GetMatrix();
|
glm::mat4 modelMatrix = e->transform.GetMatrix();
|
||||||
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(modelMatrix));
|
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(modelMatrix));
|
||||||
|
|
||||||
// Loop through all submeshes in the model component.
|
for (const auto &mesh : e->modelComponent->meshes)
|
||||||
for (const auto &mesh : e->modelComponent->meshes) {
|
{
|
||||||
// Set material properties.
|
|
||||||
glUniform3fv(glGetUniformLocation(shaderProgram, "materialDiffuse"), 1, glm::value_ptr(mesh.diffuseColor));
|
glUniform3fv(glGetUniformLocation(shaderProgram, "materialDiffuse"), 1, glm::value_ptr(mesh.diffuseColor));
|
||||||
glUniform3fv(glGetUniformLocation(shaderProgram, "materialSpecular"), 1, glm::value_ptr(mesh.specularColor));
|
glUniform3fv(glGetUniformLocation(shaderProgram, "materialSpecular"), 1, glm::value_ptr(mesh.specularColor));
|
||||||
glUniform1f(glGetUniformLocation(shaderProgram, "materialShininess"), mesh.shininess);
|
glUniform1f(glGetUniformLocation(shaderProgram, "materialShininess"), mesh.shininess);
|
||||||
|
|
||||||
// Bind diffuse texture if available.
|
if (mesh.diffuseTexture != 0)
|
||||||
if (mesh.diffuseTexture != 0) {
|
{
|
||||||
glUniform1i(glGetUniformLocation(shaderProgram, "useDiffuseTexture"), 1);
|
glUniform1i(glGetUniformLocation(shaderProgram, "useDiffuseTexture"), 1);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, mesh.diffuseTexture);
|
glBindTexture(GL_TEXTURE_2D, mesh.diffuseTexture);
|
||||||
glUniform1i(glGetUniformLocation(shaderProgram, "diffuseTexture"), 0);
|
glUniform1i(glGetUniformLocation(shaderProgram, "diffuseTexture"), 0);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
glUniform1i(glGetUniformLocation(shaderProgram, "useDiffuseTexture"), 0);
|
glUniform1i(glGetUniformLocation(shaderProgram, "useDiffuseTexture"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind normal map if available.
|
if (mesh.normalTexture != 0)
|
||||||
if (mesh.normalTexture != 0) {
|
{
|
||||||
glUniform1i(glGetUniformLocation(shaderProgram, "useNormalMap"), 1);
|
glUniform1i(glGetUniformLocation(shaderProgram, "useNormalMap"), 1);
|
||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
glBindTexture(GL_TEXTURE_2D, mesh.normalTexture);
|
glBindTexture(GL_TEXTURE_2D, mesh.normalTexture);
|
||||||
glUniform1i(glGetUniformLocation(shaderProgram, "normalMap"), 1);
|
glUniform1i(glGetUniformLocation(shaderProgram, "normalMap"), 1);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
glUniform1i(glGetUniformLocation(shaderProgram, "useNormalMap"), 0);
|
glUniform1i(glGetUniformLocation(shaderProgram, "useNormalMap"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind the submesh's VAO and draw its elements.
|
|
||||||
glBindVertexArray(mesh.VAO);
|
glBindVertexArray(mesh.VAO);
|
||||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mesh.indices.size()), GL_UNSIGNED_INT, 0);
|
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mesh.indices.size()), GL_UNSIGNED_INT, 0);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
@ -356,11 +530,34 @@ ImTextureID Engine::RenderScene(const glm::mat4 &view, const glm::mat4 &projecti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Draw Skybox
|
||||||
|
glDepthFunc(GL_LEQUAL); // Allow skybox fragments to pass depth test.
|
||||||
|
glUseProgram(skyboxShaderProgram);
|
||||||
|
|
||||||
|
glm::mat4 viewNoTrans = glm::mat4(glm::mat3(view));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(skyboxShaderProgram, "view"), 1, GL_FALSE, glm::value_ptr(viewNoTrans));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(skyboxShaderProgram, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||||
|
|
||||||
|
// Bind skybox VAO and cubemap texture.
|
||||||
|
glBindVertexArray(skyboxVAO);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_CUBE_MAP, skyboxCubemap);
|
||||||
|
glUniform1i(glGetUniformLocation(skyboxShaderProgram, "skybox"), 0);
|
||||||
|
|
||||||
|
// Draw the cube (36 vertices)
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
glDepthFunc(GL_LESS); // Restore default depth function.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
return (ImTextureID)(intptr_t)colorTexture;
|
return (ImTextureID)(intptr_t)colorTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ImTextureID Engine::GetFinalRenderingTexture()
|
ImTextureID Engine::GetFinalRenderingTexture()
|
||||||
{
|
{
|
||||||
return (ImTextureID)(intptr_t)colorTexture;
|
return (ImTextureID)(intptr_t)colorTexture;
|
||||||
|
BIN
Three-Labs.exe
@ -2,12 +2,12 @@ entities:
|
|||||||
- type: cube
|
- type: cube
|
||||||
transform:
|
transform:
|
||||||
position:
|
position:
|
||||||
|
- -2
|
||||||
|
- 0
|
||||||
- 0
|
- 0
|
||||||
- -1.29999995
|
|
||||||
- 0.600000024
|
|
||||||
rotation:
|
rotation:
|
||||||
- 0
|
- 0
|
||||||
- 90
|
- 0
|
||||||
- 0
|
- 0
|
||||||
scale:
|
scale:
|
||||||
- 0.00999999978
|
- 0.00999999978
|
||||||
@ -16,9 +16,9 @@ entities:
|
|||||||
model:
|
model:
|
||||||
modelPath: ./assets/models/sponza.obj
|
modelPath: ./assets/models/sponza.obj
|
||||||
globalDiffuseColor:
|
globalDiffuseColor:
|
||||||
- 1
|
- 0.800000012
|
||||||
- 1
|
- 0.200000003
|
||||||
- 1
|
- 0.200000003
|
||||||
globalSpecularColor:
|
globalSpecularColor:
|
||||||
- 1
|
- 1
|
||||||
- 1
|
- 1
|
||||||
@ -40,10 +40,10 @@ entities:
|
|||||||
- 1
|
- 1
|
||||||
light:
|
light:
|
||||||
color:
|
color:
|
||||||
- 0.995098054
|
- 1
|
||||||
- 0.878314674
|
- 1
|
||||||
- 0.814614594
|
- 1
|
||||||
intensity: 2.29999995
|
intensity: 1.5
|
||||||
- type: light
|
- type: light
|
||||||
transform:
|
transform:
|
||||||
position:
|
position:
|
||||||
@ -60,7 +60,7 @@ entities:
|
|||||||
- 1
|
- 1
|
||||||
light:
|
light:
|
||||||
color:
|
color:
|
||||||
- 0
|
- 0.200000003
|
||||||
- 2.38418579e-07
|
- 0.200000003
|
||||||
- 1
|
- 1
|
||||||
intensity: 1.79999995
|
intensity: 0
|
BIN
assets/skybox.png
Normal file
After Width: | Height: | Size: 11 MiB |
BIN
assets/skybox.zip
Normal file
BIN
assets/skybox/back.jpg
Normal file
After Width: | Height: | Size: 723 KiB |
BIN
assets/skybox/bottom.jpg
Normal file
After Width: | Height: | Size: 274 KiB |
BIN
assets/skybox/front.jpg
Normal file
After Width: | Height: | Size: 462 KiB |
BIN
assets/skybox/left.jpg
Normal file
After Width: | Height: | Size: 588 KiB |
BIN
assets/skybox/right.jpg
Normal file
After Width: | Height: | Size: 525 KiB |
BIN
assets/skybox/top.jpg
Normal file
After Width: | Height: | Size: 338 KiB |
42
imgui.ini
@ -15,9 +15,9 @@ DockId=0x00000001,0
|
|||||||
|
|
||||||
[Window][Rendered Output]
|
[Window][Rendered Output]
|
||||||
Pos=247,0
|
Pos=247,0
|
||||||
Size=772,800
|
Size=772,601
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000002,0
|
DockId=0x00000007,0
|
||||||
|
|
||||||
[Window][Editor]
|
[Window][Editor]
|
||||||
Pos=176,231
|
Pos=176,231
|
||||||
@ -31,30 +31,30 @@ Collapsed=0
|
|||||||
DockId=0x00000004,0
|
DockId=0x00000004,0
|
||||||
|
|
||||||
[Window][Entity List]
|
[Window][Entity List]
|
||||||
Pos=0,78
|
Pos=0,0
|
||||||
Size=245,722
|
Size=245,800
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000005,0
|
||||||
|
|
||||||
|
[Window][Scene File]
|
||||||
|
Pos=247,603
|
||||||
|
Size=772,197
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000008,0
|
DockId=0x00000008,0
|
||||||
|
|
||||||
[Window][Scene File]
|
|
||||||
Pos=0,0
|
|
||||||
Size=245,76
|
|
||||||
Collapsed=0
|
|
||||||
DockId=0x00000007,0
|
|
||||||
|
|
||||||
[Window][Edit Model]
|
[Window][Edit Model]
|
||||||
Pos=246,-1
|
Pos=284,3
|
||||||
Size=886,794
|
Size=886,1171
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Docking][Data]
|
[Docking][Data]
|
||||||
DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=0,0 Size=1280,800 Split=X Selected=0xB6999AB4
|
DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=0,0 Size=1280,800 Split=X Selected=0xB6999AB4
|
||||||
DockNode ID=0x00000005 Parent=0x08BD597D SizeRef=245,800 Split=Y Selected=0x5A1EAB5B
|
DockNode ID=0x00000005 Parent=0x08BD597D SizeRef=245,800 Selected=0x5A1EAB5B
|
||||||
DockNode ID=0x00000007 Parent=0x00000005 SizeRef=245,76 Selected=0xE1A4FD08
|
DockNode ID=0x00000006 Parent=0x08BD597D SizeRef=1033,800 Split=X
|
||||||
DockNode ID=0x00000008 Parent=0x00000005 SizeRef=245,722 Selected=0x5A1EAB5B
|
DockNode ID=0x00000003 Parent=0x00000006 SizeRef=772,800 Split=X
|
||||||
DockNode ID=0x00000006 Parent=0x08BD597D SizeRef=1033,800 Split=X
|
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=272,800 Selected=0x5098C5B2
|
||||||
DockNode ID=0x00000003 Parent=0x00000006 SizeRef=772,800 Split=X
|
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1006,800 Split=Y Selected=0xB6999AB4
|
||||||
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=272,800 Selected=0x5098C5B2
|
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=1412,978 CentralNode=1 Selected=0xB6999AB4
|
||||||
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1006,800 CentralNode=1 Selected=0xB6999AB4
|
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=1412,197 Selected=0xE1A4FD08
|
||||||
DockNode ID=0x00000004 Parent=0x00000006 SizeRef=259,800 Selected=0x82A01C92
|
DockNode ID=0x00000004 Parent=0x00000006 SizeRef=259,800 Selected=0x82A01C92
|
||||||
|
|
||||||
|