Compare commits
15 Commits
windows
...
fec93b098b
Author | SHA1 | Date | |
---|---|---|---|
fec93b098b | |||
4a9f45b6ef | |||
fdb891d860 | |||
5bcfb18296 | |||
303b931fb7 | |||
69dbe5ae2f | |||
de6496ff81 | |||
807e0ce9d9 | |||
58e25b530b | |||
39f528d7ad | |||
6dc269ce13 | |||
9d5bb51463 | |||
c5d5536836 | |||
0d147adfe5 | |||
67ba331ba5 |
@ -1,55 +1,67 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
project(CodingGame LANGUAGES C CXX)
|
project(CodingGame LANGUAGES C CXX)
|
||||||
|
|
||||||
# --- deps via vcpkg ---
|
if (UNIX)
|
||||||
# (vcpkg installs decide static vs shared; no "SDL3-shared" component needed)
|
include(FetchContent)
|
||||||
find_package(SDL3 CONFIG REQUIRED)
|
FetchContent_Declare(
|
||||||
find_package(OpenGL REQUIRED)
|
glm
|
||||||
find_package(GLEW CONFIG REQUIRED)
|
GIT_REPOSITORY https://github.com/g-truc/glm.git
|
||||||
find_package(glm CONFIG REQUIRED)
|
GIT_TAG bf71a834948186f4097caa076cd2663c69a10e1e #refs/tags/1.0.1
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(glm)
|
||||||
|
|
||||||
|
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3-shared)
|
||||||
|
find_package(OpenGL REQUIRED)
|
||||||
|
find_package(GLEW REQUIRED)
|
||||||
|
elseif (MSVC) # vcpkg
|
||||||
|
find_package(SDL3 CONFIG REQUIRED)
|
||||||
|
find_package(OpenGL REQUIRED)
|
||||||
|
find_package(GLEW CONFIG REQUIRED)
|
||||||
|
find_package(glm CONFIG REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Add -ggdb to debug builds
|
||||||
|
# set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -ggdb")
|
||||||
|
# set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb")
|
||||||
|
|
||||||
# --- exe ---
|
|
||||||
add_executable(CodingGame
|
add_executable(CodingGame
|
||||||
src/prelude.cpp
|
src/prelude.cpp
|
||||||
src/file_manager.cpp
|
src/file_manager.cpp
|
||||||
src/shader.cpp
|
src/shader.cpp
|
||||||
src/block.cpp
|
src/block.cpp
|
||||||
src/vertex.cpp
|
src/vertex.cpp
|
||||||
src/texture.cpp
|
src/texture.cpp
|
||||||
src/model.cpp
|
src/model.cpp
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set_property(TARGET CodingGame PROPERTY CXX_STANDARD 17)
|
set_property(TARGET CodingGame PROPERTY CXX_STANDARD 17)
|
||||||
set_property(TARGET CodingGame PROPERTY CXX_STANDARD_REQUIRED ON)
|
set_property(TARGET CodingGame PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
file(COPY ${CMAKE_SOURCE_DIR}/src/shaders DESTINATION ${CMAKE_BINARY_DIR}/)
|
file(COPY src/shaders DESTINATION ${CMAKE_BINARY_DIR}/)
|
||||||
|
|
||||||
target_include_directories(CodingGame PRIVATE
|
target_include_directories(CodingGame PRIVATE
|
||||||
${CMAKE_SOURCE_DIR}/include
|
${CMAKE_SOURCE_DIR}/include
|
||||||
${CMAKE_SOURCE_DIR}/contrib
|
${CMAKE_SOURCE_DIR}/contrib
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(CodingGame PRIVATE
|
target_link_libraries(CodingGame PRIVATE
|
||||||
glm::glm
|
SDL3::SDL3
|
||||||
OpenGL::GL
|
OpenGL::GL
|
||||||
SDL3::SDL3 # vcpkg’s SDL3 target
|
GLEW::GLEW
|
||||||
GLEW::GLEW
|
glm::glm
|
||||||
)
|
)
|
||||||
|
|
||||||
# Debug flags per toolchain
|
# Debug flags
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_compile_options(CodingGame PRIVATE $<$<CONFIG:Debug>:/Zi>)
|
target_compile_options(CodingGame PRIVATE $<$<CONFIG:Debug>:/Zi>)
|
||||||
target_link_options(CodingGame PRIVATE $<$<CONFIG:Debug>:/DEBUG:FULL>)
|
target_link_options(CodingGame PRIVATE $<$<CONFIG:Debug>:/DEBUG:FULL>)
|
||||||
else()
|
else()
|
||||||
target_compile_options(CodingGame PRIVATE $<$<CONFIG:Debug>:-ggdb>)
|
target_compile_options(CodingGame PRIVATE $<$<CONFIG:Debug>:-ggdb>)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# --- copy runtime DLLs next to the exe on Windows ---
|
|
||||||
# (CMake 3.21+)
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
add_custom_command(TARGET CodingGame POST_BUILD
|
add_custom_command(TARGET CodingGame POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
$<TARGET_RUNTIME_DLLS:CodingGame> $<TARGET_FILE_DIR:CodingGame>
|
$<TARGET_RUNTIME_DLLS:CodingGame> $<TARGET_FILE_DIR:CodingGame>
|
||||||
COMMAND_EXPAND_LISTS)
|
COMMAND_EXPAND_LISTS)
|
||||||
endif()
|
endif()
|
29
README.md
Normal file
29
README.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
|
||||||
|
# Project Description
|
||||||
|
|
||||||
|
This is a basic future game engine for OpenGL 3D rendered games
|
||||||
|
|
||||||
|
## Building on Windows
|
||||||
|
|
||||||
|
In order to configure and run project on windows platform use following commands.
|
||||||
|
|
||||||
|
Configuring:
|
||||||
|
|
||||||
|
```console
|
||||||
|
cmake -S . -B build `
|
||||||
|
-G "Visual Studio 17 2022" -A x64 `
|
||||||
|
-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake `
|
||||||
|
-DVCPKG_TARGET_TRIPLET=x64-windows `
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug
|
||||||
|
```
|
||||||
|
|
||||||
|
## Multi-GPU Devices
|
||||||
|
|
||||||
|
If you want to use non-primary GPU on your device when launching the game specifically on Linux you should specify additional environment variables before running. For example in my case I have a hybrid gaming laptop with 2 GPUs AMD from CPU and NVIDIA discrete.
|
||||||
|
|
||||||
|
The run command in that case would look following:
|
||||||
|
|
||||||
|
```console
|
||||||
|
__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia ./build/CodingGame
|
||||||
|
```
|
25
WINDOWS.md
25
WINDOWS.md
@ -1,25 +0,0 @@
|
|||||||
|
|
||||||
# Setup VCPKG
|
|
||||||
|
|
||||||
```console
|
|
||||||
git clone https://github.com/microsoft/vcpkg C:\vcpkg
|
|
||||||
C:\vcpkg\bootstrap-vcpkg.bat
|
|
||||||
# install deps for 64-bit Windows
|
|
||||||
C:\vcpkg\vcpkg install sdl3 glew glm --triplet x64-windows
|
|
||||||
```
|
|
||||||
|
|
||||||
# Configure
|
|
||||||
|
|
||||||
```console
|
|
||||||
cmake -S . -B build `
|
|
||||||
-G "Visual Studio 17 2022" -A x64 `
|
|
||||||
-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake `
|
|
||||||
-DVCPKG_TARGET_TRIPLET=x64-windows `
|
|
||||||
-DCMAKE_BUILD_TYPE=Debug
|
|
||||||
```
|
|
||||||
|
|
||||||
# Build
|
|
||||||
|
|
||||||
```console
|
|
||||||
cmake --build build --config Debug
|
|
||||||
```
|
|
@ -2,6 +2,7 @@
|
|||||||
#define MODEL_H_
|
#define MODEL_H_
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <filesystem>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -63,6 +64,8 @@ private:
|
|||||||
glm::vec3 m_diffuse { 0.8f, 0.8f, 0.8f };
|
glm::vec3 m_diffuse { 0.8f, 0.8f, 0.8f };
|
||||||
glm::vec3 m_specular { 1.0f, 1.0f, 1.0f };
|
glm::vec3 m_specular { 1.0f, 1.0f, 1.0f };
|
||||||
float m_shininess { 32.0f };
|
float m_shininess { 32.0f };
|
||||||
|
float m_opacity { 1.0f };
|
||||||
|
int m_illum { 2 };
|
||||||
|
|
||||||
std::unique_ptr<Texture> m_diffuse_tex { nullptr };
|
std::unique_ptr<Texture> m_diffuse_tex { nullptr };
|
||||||
public:
|
public:
|
||||||
@ -76,12 +79,16 @@ public:
|
|||||||
inline const float GetSpecularWeight() const { return m_shininess; }
|
inline const float GetSpecularWeight() const { return m_shininess; }
|
||||||
inline const bool HasDiffuseTexture() const { return m_diffuse_tex != nullptr; }
|
inline const bool HasDiffuseTexture() const { return m_diffuse_tex != nullptr; }
|
||||||
inline const Texture* GetDiffuseTexture() const { return m_diffuse_tex.get(); }
|
inline const Texture* GetDiffuseTexture() const { return m_diffuse_tex.get(); }
|
||||||
|
inline const float GetOpacity() const { return m_opacity; }
|
||||||
|
inline const int GetIllumination() const { return m_illum; }
|
||||||
public:
|
public:
|
||||||
inline void SetAmbientColor(glm::vec3 ambient) { m_ambient = ambient; }
|
inline void SetAmbientColor(glm::vec3 ambient) { m_ambient = ambient; }
|
||||||
inline void SetDiffuseColor(glm::vec3 diffuse) { m_diffuse = diffuse; }
|
inline void SetDiffuseColor(glm::vec3 diffuse) { m_diffuse = diffuse; }
|
||||||
inline void SetSpecularColor(glm::vec3 specular) { m_specular = specular; }
|
inline void SetSpecularColor(glm::vec3 specular) { m_specular = specular; }
|
||||||
inline void SetSpecularWeight(float weight) { m_shininess = weight; }
|
inline void SetSpecularWeight(float weight) { m_shininess = weight; }
|
||||||
inline void SetDiffuseTexture(std::unique_ptr<Texture>&& texture) { m_diffuse_tex = std::move(texture); }
|
inline void SetDiffuseTexture(std::unique_ptr<Texture>&& texture) { m_diffuse_tex = std::move(texture); }
|
||||||
|
inline void SetOpacity(float opacity) { m_opacity = opacity; }
|
||||||
|
inline void SetIllumination(float illum) { m_illum = illum; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Mesh {
|
class Mesh {
|
||||||
@ -120,7 +127,7 @@ public:
|
|||||||
static Object LoadFile(const std::string& filename);
|
static Object LoadFile(const std::string& filename);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void LoadMaterials(const std::string& filename);
|
void LoadMaterials(const std::filesystem::path& filename);
|
||||||
private:
|
private:
|
||||||
void AddMaterial(std::string name, std::shared_ptr<Material> material);
|
void AddMaterial(std::string name, std::shared_ptr<Material> material);
|
||||||
std::shared_ptr<Material> GetMaterial(std::string name);
|
std::shared_ptr<Material> GetMaterial(std::string name);
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
#ifndef PRELUDE_H_
|
#ifndef PRELUDE_H_
|
||||||
#define PRELUDE_H_
|
#define PRELUDE_H_
|
||||||
// #define GLEW_STATIC
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#define GLEW_STATIC
|
||||||
|
#endif
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|
||||||
#include "SDL3/SDL.h"
|
#include "SDL3/SDL.h"
|
||||||
|
|
||||||
struct RenderContext {
|
struct RenderContext {
|
||||||
|
229
src/main.bkp.cpp
229
src/main.bkp.cpp
@ -1,229 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include <glm/ext/matrix_transform.hpp>
|
|
||||||
#include <glm/ext/matrix_clip_space.hpp>
|
|
||||||
#include <GL/glew.h>
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
|
|
||||||
#include "shader.h"
|
|
||||||
#include "file_manager.h"
|
|
||||||
#include "prelude.h"
|
|
||||||
#include "block.h"
|
|
||||||
#include "vertex.h"
|
|
||||||
#include "model.h"
|
|
||||||
|
|
||||||
#define WIDTH 1024
|
|
||||||
#define HEIGHT 768
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
|
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8);
|
|
||||||
|
|
||||||
SDL_Window *window = SDL_CreateWindow("OpenGL Test", WIDTH, HEIGHT, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE|SDL_WINDOW_ALWAYS_ON_TOP);
|
|
||||||
|
|
||||||
SDL_GLContext glcontext = SDL_GL_CreateContext(window);
|
|
||||||
|
|
||||||
glewExperimental = GL_TRUE;
|
|
||||||
if (GLEW_OK != glewInit()) {
|
|
||||||
fprintf(stderr, "Could not initialize GLEW!\n");
|
|
||||||
SDL_GL_DestroyContext(glcontext);
|
|
||||||
SDL_DestroyWindow(window);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
glEnable(GL_DEBUG_OUTPUT);
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
|
||||||
glDebugMessageCallback(MessageCallback, 0);
|
|
||||||
|
|
||||||
// brightness multipliers for faces
|
|
||||||
const float FACE_BRIGHTNESS[6] = {
|
|
||||||
1.0f, // front
|
|
||||||
0.7f, // right
|
|
||||||
0.5f, // back
|
|
||||||
0.7f, // left
|
|
||||||
1.2f, // top
|
|
||||||
0.4f // bottom
|
|
||||||
};
|
|
||||||
|
|
||||||
// position, normal, color
|
|
||||||
glm::vec4 cubeColor = {1.0f, 0.5f, 0.31f, 1.0f};
|
|
||||||
std::vector<Point> cubeVerts = {
|
|
||||||
// front face (z = 0, normal = +Z)
|
|
||||||
{ {-0.5f, -0.5f, 0.5f}, {0.f, 0.f, 1.f}, cubeColor },
|
|
||||||
{ {0.5f, -0.5f, 0.5f}, {0.f, 0.f, 1.f}, cubeColor },
|
|
||||||
{ {0.5f, 0.5f, 0.5f}, {0.f, 0.f, 1.f}, cubeColor },
|
|
||||||
{ {-0.5f, 0.5f, 0.5f}, {0.f, 0.f, 1.f}, cubeColor },
|
|
||||||
|
|
||||||
// back face (z = 1, normal = -Z)
|
|
||||||
{ {-0.5f, -0.5f, -0.5f}, {0.f, 0.f, -1.f}, cubeColor },
|
|
||||||
{ {0.5f, -0.5f, -0.5f}, {0.f, 0.f, -1.f}, cubeColor },
|
|
||||||
{ {0.5f, 0.5f, -0.5f}, {0.f, 0.f, -1.f}, cubeColor },
|
|
||||||
{ {-0.5f, 0.5f, -0.5f}, {0.f, 0.f, -1.f}, cubeColor },
|
|
||||||
|
|
||||||
// left face (x = 0, normal = -X)
|
|
||||||
{ {-0.5f, -0.5f, -0.5f}, {-1.f, 0.f, 0.f}, cubeColor },
|
|
||||||
{ {-0.5f, -0.5f, 0.5f}, {-1.f, 0.f, 0.f}, cubeColor },
|
|
||||||
{ {-0.5f, 0.5f, 0.5f}, {-1.f, 0.f, 0.f}, cubeColor },
|
|
||||||
{ {-0.5f, 0.5f, -0.5f}, {-1.f, 0.f, 0.f}, cubeColor },
|
|
||||||
|
|
||||||
// right face (x = 1, normal = +X)
|
|
||||||
{ {0.5f, -0.5f, -0.5f}, {1.f, 0.f, 0.f}, cubeColor },
|
|
||||||
{ {0.5f, -0.5f, 0.5f}, {1.f, 0.f, 0.f}, cubeColor },
|
|
||||||
{ {0.5f, 0.5f, 0.5f}, {1.f, 0.f, 0.f}, cubeColor },
|
|
||||||
{ {0.5f, 0.5f, -0.5f}, {1.f, 0.f, 0.f}, cubeColor },
|
|
||||||
|
|
||||||
// top face (y = 1, normal = +Y)
|
|
||||||
{ {-0.5f, 0.5f, 0.5f}, {0.f, 1.f, 0.f}, cubeColor },
|
|
||||||
{ {0.5f, 0.5f, 0.5f}, {0.f, 1.f, 0.f}, cubeColor },
|
|
||||||
{ {0.5f, 0.5f, -0.5f}, {0.f, 1.f, 0.f}, cubeColor },
|
|
||||||
{ {-0.5f, 0.5f, -0.5f}, {0.f, 1.f, 0.f}, cubeColor },
|
|
||||||
|
|
||||||
// bottom face (y = 0, normal = -Y)
|
|
||||||
{ {-0.5f, -0.5f, 0.5f}, {0.f, -1.f, 0.f}, cubeColor },
|
|
||||||
{ {0.5f, -0.5f, 0.5f}, {0.f, -1.f, 0.f}, cubeColor },
|
|
||||||
{ {0.5f, -0.5f, -0.5f}, {0.f, -1.f, 0.f}, cubeColor },
|
|
||||||
{ {-0.5f, -0.5f, -0.5f}, {0.f, -1.f, 0.f}, cubeColor },
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<unsigned int> cubeIndices = {
|
|
||||||
0,1,2, 2,3,0, // front
|
|
||||||
4,5,6, 6,7,4, // back
|
|
||||||
8,9,10, 10,11,8, // left
|
|
||||||
12,13,14, 14,15,12, // right
|
|
||||||
16,17,18, 18,19,16, // top
|
|
||||||
20,21,22, 22,23,20 // bottom
|
|
||||||
};
|
|
||||||
|
|
||||||
Vertices vertices;
|
|
||||||
for (auto &v : cubeVerts) vertices.PushVertex(v);
|
|
||||||
for (auto i : cubeIndices) vertices.PushIndex(i);
|
|
||||||
vertices.Upload();
|
|
||||||
|
|
||||||
Shader simpleShader;
|
|
||||||
simpleShader.init(
|
|
||||||
FileManager::read("./src/shaders/simple.vs"),
|
|
||||||
FileManager::read("./src/shaders/simple.fs")
|
|
||||||
);
|
|
||||||
|
|
||||||
int screenWidth = WIDTH, screenHeight = HEIGHT;
|
|
||||||
|
|
||||||
glm::vec3 cameraPosition(0.f, 0.f, 2.f);
|
|
||||||
glm::vec3 cameraViewDirection(0.f, 0.f, -1.f);
|
|
||||||
// glm::vec3 lightPosition(1.f, 3.5f, -2.f);
|
|
||||||
glm::vec3 lightPosition = cameraPosition;
|
|
||||||
|
|
||||||
glm::mat4 model(1.f);
|
|
||||||
|
|
||||||
glm::mat4 view = glm::lookAt(
|
|
||||||
cameraPosition,
|
|
||||||
cameraPosition + cameraViewDirection,
|
|
||||||
glm::vec3(0.f, 1.f, 0.f)
|
|
||||||
);
|
|
||||||
|
|
||||||
glm::mat4 projection = glm::perspective(
|
|
||||||
(float)M_PI_2,
|
|
||||||
(float)screenWidth / (float)screenHeight,
|
|
||||||
0.01f,
|
|
||||||
100.0f
|
|
||||||
);
|
|
||||||
|
|
||||||
float angle = 3.45f;
|
|
||||||
Uint64 lastTicks = SDL_GetTicks();
|
|
||||||
|
|
||||||
Object cube = Object::LoadFile("./assets/cube.obj");
|
|
||||||
Object monkey = Object::LoadFile("./assets/monkey.obj");
|
|
||||||
|
|
||||||
bool paused = false;
|
|
||||||
|
|
||||||
bool quit = false;
|
|
||||||
while (!quit) {
|
|
||||||
Uint64 currentTicks = SDL_GetTicks();
|
|
||||||
float deltaTime = (currentTicks - lastTicks) / 1000.0f; // seconds
|
|
||||||
|
|
||||||
lastTicks = currentTicks;
|
|
||||||
|
|
||||||
SDL_Event event;
|
|
||||||
while(SDL_PollEvent(&event)) {
|
|
||||||
switch (event.type) {
|
|
||||||
case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
|
|
||||||
case SDL_EVENT_QUIT:
|
|
||||||
quit = true;
|
|
||||||
break;
|
|
||||||
case SDL_EVENT_WINDOW_RESIZED:
|
|
||||||
int width, height;
|
|
||||||
if (SDL_GetWindowSize(window, &width, &height)) {
|
|
||||||
glViewport(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
width,
|
|
||||||
height);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SDL_EVENT_KEY_DOWN:
|
|
||||||
switch (event.key.key) {
|
|
||||||
case SDLK_SPACE:
|
|
||||||
paused = !paused;
|
|
||||||
break;
|
|
||||||
// case SDLK_F5:
|
|
||||||
// reload_shaders(&context);
|
|
||||||
// break;
|
|
||||||
default: break;
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
default: break;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// update rotation
|
|
||||||
if (!paused) {
|
|
||||||
angle += glm::radians(45.0f) * deltaTime; // 72° per second
|
|
||||||
if (angle > glm::two_pi<float>()) {
|
|
||||||
angle -= glm::two_pi<float>(); // keep value small
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// std::cout << "angle = " << angle << std::endl;
|
|
||||||
|
|
||||||
glClearColor(0x18/255.0f, 0x18/255.0f, 0x18/255.0f, 1);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
|
|
||||||
// Triangle render
|
|
||||||
{
|
|
||||||
simpleShader.use();
|
|
||||||
|
|
||||||
model = glm::rotate(
|
|
||||||
glm::mat4(1.f),
|
|
||||||
angle,
|
|
||||||
glm::vec3(0.8f, -0.4f, 0.5f)
|
|
||||||
);
|
|
||||||
|
|
||||||
// lightPosition -= glm::vec3(0.05f, 0.f, 0.f) * deltaTime;
|
|
||||||
|
|
||||||
simpleShader.setMat4("u_model", model);
|
|
||||||
simpleShader.setMat4("u_view", view);
|
|
||||||
simpleShader.setMat4("u_projection", projection);
|
|
||||||
|
|
||||||
simpleShader.setVec3("lightColor", glm::vec3(1.0f, 1.0f, 1.0f));
|
|
||||||
simpleShader.setVec3("lightPos", lightPosition);
|
|
||||||
simpleShader.setVec3("viewPos", cameraPosition);
|
|
||||||
simpleShader.setFloat("ambientStrength", 0.2f);
|
|
||||||
simpleShader.setFloat("specularStrength", 0.5f);
|
|
||||||
|
|
||||||
vertices.Draw();
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_GL_SwapWindow(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_GL_DestroyContext(glcontext);
|
|
||||||
SDL_DestroyWindow(window);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,6 +1,10 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
// #ifdef WIN32
|
||||||
#define _USE_MATH_DEFINES
|
#define _USE_MATH_DEFINES
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
// #endif
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/ext/quaternion_geometric.hpp>
|
#include <glm/ext/quaternion_geometric.hpp>
|
||||||
|
@ -86,7 +86,7 @@ Object::Object() {
|
|||||||
m_texCoords = std::vector<glm::vec2>();
|
m_texCoords = std::vector<glm::vec2>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::LoadMaterials(const std::string& filename) {
|
void Object::LoadMaterials(const std::filesystem::path& filename) {
|
||||||
std::ifstream file(filename);
|
std::ifstream file(filename);
|
||||||
|
|
||||||
std::string currentMaterialName;
|
std::string currentMaterialName;
|
||||||
@ -142,6 +142,20 @@ void Object::LoadMaterials(const std::string& filename) {
|
|||||||
currentMaterial->SetDiffuseColor(glm::vec3(r, g, b));
|
currentMaterial->SetDiffuseColor(glm::vec3(r, g, b));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MtlElement::D:
|
||||||
|
{
|
||||||
|
float d;
|
||||||
|
iss >> d;
|
||||||
|
currentMaterial->SetOpacity(d);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MtlElement::ILLUM:
|
||||||
|
{
|
||||||
|
int illum;
|
||||||
|
iss >> illum;
|
||||||
|
currentMaterial->SetIllumination(illum);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MtlElement::MAP_KD:
|
case MtlElement::MAP_KD:
|
||||||
{
|
{
|
||||||
std::string texturePath;
|
std::string texturePath;
|
||||||
@ -215,7 +229,7 @@ Object Object::LoadFile(const std::string& filename) {
|
|||||||
iss >> mtlFile;
|
iss >> mtlFile;
|
||||||
std::filesystem::path fullPath = filename;
|
std::filesystem::path fullPath = filename;
|
||||||
std::filesystem::path mtlPath = fullPath.replace_filename(mtlFile);
|
std::filesystem::path mtlPath = fullPath.replace_filename(mtlFile);
|
||||||
obj.LoadMaterials(mtlPath.u8string());
|
obj.LoadMaterials(mtlPath);
|
||||||
std::cout << "loaded mtl at '" << mtlPath << "' with "
|
std::cout << "loaded mtl at '" << mtlPath << "' with "
|
||||||
<< obj.m_materials.size() << " materials" << std::endl;
|
<< obj.m_materials.size() << " materials" << std::endl;
|
||||||
break;
|
break;
|
||||||
@ -325,7 +339,10 @@ void Object::Render(Shader& shader)
|
|||||||
auto material = GetMaterial(mesh.materialName);
|
auto material = GetMaterial(mesh.materialName);
|
||||||
|
|
||||||
shader.setFloat("ambientStrength", 0.2f);
|
shader.setFloat("ambientStrength", 0.2f);
|
||||||
shader.setFloat("specularStrength", material->GetSpecularWeight());
|
shader.setFloat("shininess", material->GetSpecularWeight());
|
||||||
|
shader.setFloat("opacity", material->GetOpacity());
|
||||||
|
shader.setBool("useSpecular", material->GetIllumination() >= 2);
|
||||||
|
shader.setFloat("specularStrength", 1.0f);
|
||||||
shader.setVec3("ambientColor", material->GetAmbientColor());
|
shader.setVec3("ambientColor", material->GetAmbientColor());
|
||||||
shader.setVec3("diffuseColor", material->GetDiffuseColor());
|
shader.setVec3("diffuseColor", material->GetDiffuseColor());
|
||||||
shader.setVec3("specularColor", material->GetSpecularColor());
|
shader.setVec3("specularColor", material->GetSpecularColor());
|
||||||
|
@ -6,7 +6,9 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "prelude.h"
|
#include "prelude.h"
|
||||||
|
|
||||||
// #define GLEW_STATIC
|
#ifndef WIN32
|
||||||
|
#define GLEW_STATIC
|
||||||
|
#endif
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|
||||||
#define SCREEN_WIDTH 1024
|
#define SCREEN_WIDTH 1024
|
||||||
|
126
src/shaders/pbr.fs
Normal file
126
src/shaders/pbr.fs
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
// Output color
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
in vec3 vertexPos;
|
||||||
|
in vec3 vertexNormal;
|
||||||
|
in vec2 TexCoords;
|
||||||
|
|
||||||
|
uniform vec3 lightPos;
|
||||||
|
uniform vec3 viewPos;
|
||||||
|
|
||||||
|
// From Object Renderer
|
||||||
|
uniform vec3 ambientColor;
|
||||||
|
uniform vec3 diffuseColor;
|
||||||
|
uniform vec3 specularColor; // used as F0 (base reflectance)
|
||||||
|
|
||||||
|
uniform float ambientStrength;
|
||||||
|
uniform float specularStrength;
|
||||||
|
uniform float shininess; // mapped to roughness
|
||||||
|
uniform bool useSpecular;
|
||||||
|
|
||||||
|
uniform float opacity;
|
||||||
|
|
||||||
|
uniform sampler2D diffuseTex;
|
||||||
|
uniform bool useTexture;
|
||||||
|
|
||||||
|
#define LIGHT_COLOR vec3(1.0, 1.0, 1.0)
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Helper functions for Cook-Torrance BRDF
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Normal Distribution Function (GGX/Trowbridge-Reitz)
|
||||||
|
float DistributionGGX(vec3 N, vec3 H, float roughness)
|
||||||
|
{
|
||||||
|
float a = roughness * roughness;
|
||||||
|
float a2 = a * a;
|
||||||
|
float NdotH = max(dot(N, H), 0.0);
|
||||||
|
float NdotH2 = NdotH * NdotH;
|
||||||
|
|
||||||
|
float num = a2;
|
||||||
|
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
|
||||||
|
denom = 3.14159265 * denom * denom;
|
||||||
|
|
||||||
|
return num / denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Geometry function (Schlick-GGX)
|
||||||
|
float GeometrySchlickGGX(float NdotV, float roughness)
|
||||||
|
{
|
||||||
|
float r = (roughness + 1.0);
|
||||||
|
float k = (r * r) / 8.0; // remapped for direct lighting
|
||||||
|
|
||||||
|
float num = NdotV;
|
||||||
|
float denom = NdotV * (1.0 - k) + k;
|
||||||
|
|
||||||
|
return num / denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Smith's geometry function
|
||||||
|
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
|
||||||
|
{
|
||||||
|
float NdotV = max(dot(N, V), 0.0);
|
||||||
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
|
float ggx1 = GeometrySchlickGGX(NdotV, roughness);
|
||||||
|
float ggx2 = GeometrySchlickGGX(NdotL, roughness);
|
||||||
|
return ggx1 * ggx2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fresnel term (Schlick's approximation)
|
||||||
|
vec3 FresnelSchlick(float cosTheta, vec3 F0)
|
||||||
|
{
|
||||||
|
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 N = normalize(vertexNormal);
|
||||||
|
vec3 V = normalize(viewPos - vertexPos);
|
||||||
|
vec3 L = normalize(lightPos - vertexPos);
|
||||||
|
vec3 H = normalize(V + L);
|
||||||
|
|
||||||
|
// Texture or uniform color
|
||||||
|
vec3 albedo = (useTexture)
|
||||||
|
? texture(diffuseTex, TexCoords).rgb
|
||||||
|
: diffuseColor;
|
||||||
|
|
||||||
|
// Map shininess to roughness (inverse relationship)
|
||||||
|
float roughness = clamp(1.0 - (shininess / 256.0), 0.05, 1.0);
|
||||||
|
|
||||||
|
// Base reflectivity (F0)
|
||||||
|
vec3 F0 = mix(vec3(0.04), specularColor, specularStrength);
|
||||||
|
|
||||||
|
// Cook-Torrance BRDF
|
||||||
|
float NDF = DistributionGGX(N, H, roughness);
|
||||||
|
float G = GeometrySmith(N, V, L, roughness);
|
||||||
|
vec3 F = FresnelSchlick(max(dot(H, V), 0.0), F0);
|
||||||
|
|
||||||
|
vec3 numerator = NDF * G * F;
|
||||||
|
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.001;
|
||||||
|
vec3 specular = numerator / denominator;
|
||||||
|
|
||||||
|
// Energy conservation
|
||||||
|
vec3 kS = F;
|
||||||
|
vec3 kD = vec3(1.0) - kS;
|
||||||
|
kD *= (useSpecular ? 1.0 : 1.0); // keep diffuse always unless specular is off
|
||||||
|
|
||||||
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
|
|
||||||
|
vec3 diffuse = kD * albedo / 3.14159265;
|
||||||
|
vec3 radiance = LIGHT_COLOR;
|
||||||
|
|
||||||
|
vec3 Lo = (diffuse + specular) * radiance * NdotL;
|
||||||
|
|
||||||
|
// Ambient (simple, not IBL)
|
||||||
|
vec3 ambient = ambientStrength * ambientColor * albedo;
|
||||||
|
|
||||||
|
vec3 result = ambient + Lo;
|
||||||
|
|
||||||
|
// Gamma correction
|
||||||
|
result = pow(result, vec3(1.0/2.2));
|
||||||
|
|
||||||
|
FragColor = vec4(result, opacity);
|
||||||
|
}
|
@ -17,7 +17,12 @@ uniform vec3 diffuseColor;
|
|||||||
uniform vec3 specularColor;
|
uniform vec3 specularColor;
|
||||||
|
|
||||||
uniform float ambientStrength;
|
uniform float ambientStrength;
|
||||||
|
|
||||||
uniform float specularStrength;
|
uniform float specularStrength;
|
||||||
|
uniform float shininess;
|
||||||
|
uniform bool useSpecular;
|
||||||
|
|
||||||
|
uniform float opacity;
|
||||||
|
|
||||||
uniform sampler2D diffuseTex;
|
uniform sampler2D diffuseTex;
|
||||||
uniform bool useTexture;
|
uniform bool useTexture;
|
||||||
@ -33,8 +38,13 @@ void main()
|
|||||||
vec3 reflectDir = reflect(-lightDir, norm);
|
vec3 reflectDir = reflect(-lightDir, norm);
|
||||||
|
|
||||||
// Phong components
|
// Phong components
|
||||||
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
|
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), clamp(shininess, 2, 256));
|
||||||
vec3 specular = specularStrength * spec * specularColor;
|
// vec3 specular = (useSpecular) ? specularStrength * spec * specularColor : vec3(0.0);
|
||||||
|
|
||||||
|
// Blinn Phong
|
||||||
|
vec3 halfDir = normalize(lightDir + viewDir);
|
||||||
|
float spec = pow(max(dot(norm, halfDir), 0.0), clamp(shininess, 2.0, 256.0));
|
||||||
|
vec3 specular = (useSpecular) ? specularStrength * spec * specularColor : vec3(0.0);
|
||||||
|
|
||||||
float diff = max(dot(norm, lightDir), 0.0);
|
float diff = max(dot(norm, lightDir), 0.0);
|
||||||
vec3 diffuse = diff * diffuseColor;
|
vec3 diffuse = diff * diffuseColor;
|
||||||
@ -46,5 +56,6 @@ void main()
|
|||||||
: diffuseColor;
|
: diffuseColor;
|
||||||
|
|
||||||
vec3 result = (ambient + diffuse + specular) * texColor;
|
vec3 result = (ambient + diffuse + specular) * texColor;
|
||||||
FragColor = vec4(result, 1.0);
|
|
||||||
|
FragColor = vec4(result, opacity);
|
||||||
}
|
}
|
@ -10,7 +10,7 @@ std::unique_ptr<Texture> Texture::LoadFile(const std::string& filename) {
|
|||||||
auto texture = std::make_unique<Texture>();
|
auto texture = std::make_unique<Texture>();
|
||||||
|
|
||||||
int w, h, c;
|
int w, h, c;
|
||||||
unsigned char *data = stbi_load(filename.c_str(), &w, &h, &c, 0);
|
unsigned char *data = stbi_load(filename.c_str(), &w, &h, &c, 4);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
std::cerr << "ERROR: Failed to load texture under '" << filename << "'" << std::endl;
|
std::cerr << "ERROR: Failed to load texture under '" << filename << "'" << std::endl;
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
@ -26,7 +26,7 @@ std::unique_ptr<Texture> Texture::LoadFile(const std::string& filename) {
|
|||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
// TODO: automatically detect values for this function
|
// TODO: automatically detect values for this function
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||||
glGenerateMipmap(GL_TEXTURE_2D);
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
|
||||||
std::cout << "Loaded texture under '" << filename << "' with size of " << sizeof(data) << " bytes" << std::endl;
|
std::cout << "Loaded texture under '" << filename << "' with size of " << sizeof(data) << " bytes" << std::endl;
|
||||||
|
Reference in New Issue
Block a user