Skip to content
Snippets Groups Projects
Commit 59c511fa authored by Philip Trettner's avatar Philip Trettner
Browse files

live 8 prepare

parent f2e35184
No related branches found
No related tags found
No related merge requests found
......@@ -62,3 +62,4 @@ add_subdirectory(rtglive4)
add_subdirectory(rtglive5)
add_subdirectory(rtglive6)
add_subdirectory(rtglive7)
add_subdirectory(rtglive8)
# ===============================================
# Configure executable
file(GLOB_RECURSE SOURCES
"src/*.cc"
"src/*.hh"
"src/*.*sh"
"src/*.glsl"
)
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCES})
add_executable(rtglive8 ${SOURCES})
target_link_libraries(rtglive8 PUBLIC
glow
glow-extras
typed-geometry
ctracer
imgui
)
target_include_directories(rtglive8 PUBLIC "src")
# ===============================================
# Compile flags
if (MSVC)
target_compile_options(rtglive8 PUBLIC
/MP
)
else()
target_compile_options(rtglive8 PUBLIC
-Wall
-Wno-unused-variable
)
target_link_libraries(rtglive8 PUBLIC
-lstdc++fs
)
endif()
#include "LiveApp.hh"
#include <imgui/imgui.h>
#include <GLFW/glfw3.h>
#include <typed-geometry/tg-std.hh>
#include <glow/common/scoped_gl.hh>
#include <glow/common/str_utils.hh>
#include <glow/data/TextureData.hh>
#include <glow/objects/Framebuffer.hh>
#include <glow/objects/Texture2D.hh>
#include <glow/objects/TextureRectangle.hh>
#include <glow-extras/geometry/Quad.hh>
void LiveApp::init()
{
setGui(Gui::ImGui);
GlfwApp::init();
auto src_folder = glow::util::pathOf(__FILE__);
mShaderMesh = glow::Program::createFromFile(src_folder + "/mesh");
mShaderTerrain = glow::Program::createFromFile(src_folder + "/terrain");
mShaderOutput = glow::Program::createFromFile(src_folder + "/output");
mSkyBox = glow::TextureCubeMap::createFromData(glow::TextureData::createFromFileCube( //
src_folder + "/../../textures/posx.jpg", //
src_folder + "/../../textures/negx.jpg", //
src_folder + "/../../textures/posy.jpg", //
src_folder + "/../../textures/negy.jpg", //
src_folder + "/../../textures/posz.jpg", //
src_folder + "/../../textures/negz.jpg", //
glow::ColorSpace::sRGB));
mTexAlbedo = glow::Texture2D::createFromFile(src_folder + "/../../textures/debris_albedo.png", glow::ColorSpace::sRGB);
mTexNormal = glow::Texture2D::createFromFile(src_folder + "/../../textures/debris_normal.png", glow::ColorSpace::Linear);
mTexAO = glow::Texture2D::createFromFile(src_folder + "/../../textures/debris_ao.png", glow::ColorSpace::Linear);
mTexHeight = glow::Texture2D::createFromFile(src_folder + "/../../textures/debris_height.png", glow::ColorSpace::Linear);
mTexRoughness = glow::Texture2D::createFromFile(src_folder + "/../../textures/debris_roughness.png", glow::ColorSpace::Linear);
mQuad = glow::geometry::Quad<>().generate();
mTargetColor = glow::TextureRectangle::create(1, 1, GL_RGB8);
mTargetDepth = glow::TextureRectangle::create(1, 1, GL_DEPTH_COMPONENT32);
mFramebuffer = glow::Framebuffer::create("fColor", mTargetColor, mTargetDepth);
// init terrain
{
auto const some_random_value = [](int x, int y) -> float {
auto seed = (uint64_t(uint32_t(x)) << 32) | uint32_t(y);
tg::rng rng;
rng.seed(seed);
return uniform(rng, -1.f, 1.f);
};
auto const value_noise = [&](float x, float y) {
int ix = tg::ifloor(x);
int iy = tg::ifloor(y);
auto fx = x - ix;
auto fy = y - iy;
auto v00 = some_random_value(ix + 0, iy + 0);
auto v01 = some_random_value(ix + 0, iy + 1);
auto v10 = some_random_value(ix + 1, iy + 0);
auto v11 = some_random_value(ix + 1, iy + 1);
auto v0 = tg::mix(v00, v10, fx);
auto v1 = tg::mix(v01, v11, fx);
auto v = tg::mix(v0, v1, fy);
return v;
};
auto const terrain_at = [&](float x, float y) {
auto h = 0.0f;
float scale = 0.033f;
float amplitude = 1.f;
for (auto i = 0; i < 7; ++i)
{
h += value_noise(x * scale, y * scale) * amplitude;
scale *= 2;
amplitude *= 0.7f;
}
return h;
};
tg::rng rng;
mHeightMap.resize(mTerrainSize * mTerrainSize);
for (auto z = 0; z < mTerrainSize; ++z)
for (auto x = 0; x < mTerrainSize; ++x)
{
mHeightMap[idxOf(x, z)] = terrain_at(x, z) //
+ terrain_at(mTerrainSize - x - 1, z) //
+ terrain_at(x, mTerrainSize - z - 1) //
+ terrain_at(mTerrainSize - x - 1, mTerrainSize - z - 1);
}
mHeightMapTexture = glow::Texture2D::create();
{
auto tex = mHeightMapTexture->bind();
tex.setData(GL_R32F, mTerrainSize, mTerrainSize, mHeightMap);
tex.setWrap(GL_REPEAT, GL_REPEAT);
tex.generateMipmaps();
}
if (false) // old terrain
for (auto z = 0; z < mTerrainSize - 1; ++z)
for (auto x = 0; x < mTerrainSize - 1; ++x)
{
auto make_pos = [&](int x, int z) {
auto h = mHeightMap[idxOf(x, z)];
return tg::pos3(x - mTerrainSize / 2, h, z - mTerrainSize / 2);
};
auto p00 = make_pos(x + 0, z + 0);
auto p01 = make_pos(x + 0, z + 1);
auto p10 = make_pos(x + 1, z + 0);
auto p11 = make_pos(x + 1, z + 1);
debugMesh.add_triangle(p00, p11, p10, tg::color3::green);
debugMesh.add_triangle(p00, p01, p11, tg::color3::green);
}
}
auto c = tg::pos3(0, 1, 0);
auto dx = tg::vec3::unit_x;
auto dy = tg::vec3::unit_y;
auto dz = tg::vec3::unit_z;
debugMesh.add_triangle(c - dz * 0.1f, c + dz * 0.1f, c + dx, tg::color3::red);
debugMesh.add_triangle(c - dx * 0.1f, c + dx * 0.1f, c + dz, tg::color3::blue);
debugMesh.add_triangle(c - dz * 0.1f, c + dz * 0.1f, c + dy, tg::color3::green);
debugMesh.add_triangle(c - dx * 0.1f, c + dx * 0.1f, c + dy, tg::color3::green);
debugMesh.upload();
}
void LiveApp::update(float elapsedSeconds)
{
// TODO
auto const speed = 50.f;
if (mKeyDownW)
cam.pos += cam.dir * elapsedSeconds * speed;
if (mKeyDownS)
cam.pos -= cam.dir * elapsedSeconds * speed;
if (mKeyDownD)
cam.pos += cam.right() * elapsedSeconds * speed;
if (mKeyDownA)
cam.pos -= cam.right() * elapsedSeconds * speed;
}
void LiveApp::render(float elapsedSeconds)
{
auto const w = getWindowWidth();
auto const h = getWindowHeight();
cam.aspect_ratio = w / float(h);
// camera matrices
auto proj = cam.proj();
auto view = cam.view();
auto inv_proj = inverse(proj);
auto inv_view = inverse(view);
// render scene
{
auto fb = mFramebuffer->bind();
// clear screen
GLOW_SCOPED(clearColor, tg::color3::black);
GLOW_SCOPED(enable, GL_DEPTH_TEST);
GLOW_SCOPED(enable, GL_CULL_FACE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLOW_SCOPED(polygonMode, mWireframe ? GL_LINE : GL_FILL);
{
auto shader = mShaderMesh->use();
shader["uProj"] = proj;
shader["uView"] = view;
GLOW_SCOPED(disable, GL_CULL_FACE);
debugMesh.vertexArray->bind().draw();
}
// render terrain
{
auto shader = mShaderTerrain->use();
shader["uProj"] = proj;
shader["uView"] = view;
shader["uTerrainSize"] = mTerrainSize;
shader["uViewDistance"] = mViewDistance;
shader["uHeightMap"] = mHeightMapTexture;
shader["uCenterPos"] = tg::round(cam.pos);
shader["uCamPos"] = cam.pos;
shader["uTexAlbedo"] = mTexAlbedo;
shader["uTexNormal"] = mTexNormal;
shader["uTexAO"] = mTexAO;
shader["uTexHeight"] = mTexHeight;
shader["uTexRoughness"] = mTexRoughness;
shader["uSkyBox"] = mSkyBox;
shader["uEpsMultiplier"] = mEpsMultiplier;
shader["uRuntime"] = (float)glfwGetTime();
mQuad->bind().draw(mViewDistance * mViewDistance);
}
}
// read back screen pixel
{
auto fb = mFramebuffer->bind();
// GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels
auto mx = int(getMousePosition().x);
auto my = int(getWindowHeight() - getMousePosition().y - 1);
if (0 <= mx && 0 <= my && mx < getWindowWidth() && my < getWindowHeight())
{
glReadPixels(mx, my, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &mDepthBelowCursor);
tg::pos3 ndc = {mx / (getWindowWidth() - 1.f) * 2 - 1, //
my / (getWindowHeight() - 1.f) * 2 - 1, //
mDepthBelowCursor * 2 - 1};
mWorldPosBelowCursor = inv_view * inv_proj * ndc;
}
}
// write output
{
auto shader = mShaderOutput->use();
shader["uTargetColor"] = mTargetColor;
shader["uTargetDepth"] = mTargetDepth;
shader["uSkyBox"] = mSkyBox;
shader["uInvProj"] = inv_proj;
shader["uInvView"] = inv_view;
GLOW_SCOPED(disable, GL_DEPTH_TEST);
GLOW_SCOPED(disable, GL_CULL_FACE);
mQuad->bind().draw();
}
}
void LiveApp::onResize(int w, int h)
{
GlfwApp::onResize(w, h);
mTargetColor->bind().resize(w, h);
mTargetDepth->bind().resize(w, h);
}
void LiveApp::onGui()
{
if (ImGui::Begin("debug"))
{
ImGui::Checkbox("Wireframe", &mWireframe);
auto mp = getMousePosition();
ImGui::Text("mouse x: %f", mp.x);
ImGui::Text("mouse y: %f", mp.y);
ImGui::Text("depth: %f", mDepthBelowCursor);
ImGui::Text("world x: %f", mWorldPosBelowCursor.x);
ImGui::Text("world y: %f", mWorldPosBelowCursor.y);
ImGui::Text("world z: %f", mWorldPosBelowCursor.z);
ImGui::SliderInt("view distance", &mViewDistance, 10, 1000);
ImGui::SliderFloat("eps mult", &mEpsMultiplier, .1f, 10);
}
ImGui::End();
}
bool LiveApp::onMouseButton(double x, double y, int button, int action, int mods, int clickCount)
{
if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
setCursorMode(glow::glfw::CursorMode::Disabled);
if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_RELEASE)
setCursorMode(glow::glfw::CursorMode::Normal);
return true;
}
bool LiveApp::onMousePosition(double x, double y)
{
static double lastX = x;
static double lastY = y;
auto dx = float(x - lastX);
auto dy = float(y - lastY);
auto cam_speed = -360_deg / 2000;
if (isMouseButtonDown(1))
{
auto rotX = tg::rotation_around(cam_speed * dx, cam.up);
cam.dir = normalize(rotX * cam.dir);
auto rotY = tg::rotation_around(cam_speed * dy, cam.right());
cam.dir = normalize(rotY * cam.dir);
}
lastX = x;
lastY = y;
return true;
}
bool LiveApp::onKey(int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_A && action == GLFW_PRESS)
mKeyDownA = true;
if (key == GLFW_KEY_A && action == GLFW_RELEASE)
mKeyDownA = false;
if (key == GLFW_KEY_W && action == GLFW_PRESS)
mKeyDownW = true;
if (key == GLFW_KEY_W && action == GLFW_RELEASE)
mKeyDownW = false;
if (key == GLFW_KEY_D && action == GLFW_PRESS)
mKeyDownD = true;
if (key == GLFW_KEY_D && action == GLFW_RELEASE)
mKeyDownD = false;
if (key == GLFW_KEY_S && action == GLFW_PRESS)
mKeyDownS = true;
if (key == GLFW_KEY_S && action == GLFW_RELEASE)
mKeyDownS = false;
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
mKeyDownSpace = true;
if (key == GLFW_KEY_SPACE && action == GLFW_RELEASE)
mKeyDownSpace = false;
return false;
}
void mesh::upload()
{
arrayBuffer = glow::ArrayBuffer::create();
arrayBuffer->defineAttribute(&vertex::pos, "aPosition");
arrayBuffer->defineAttribute(&vertex::normal, "aNormal");
arrayBuffer->defineAttribute(&vertex::color, "aColor");
arrayBuffer->bind().setData(vertices);
vertexArray = glow::VertexArray::create(arrayBuffer, GL_TRIANGLES);
}
#pragma once
#include <glow-extras/glfw/GlfwApp.hh>
#include <typed-geometry/tg-lean.hh>
#include <glow/objects/ArrayBuffer.hh>
#include <glow/objects/Program.hh>
#include <glow/objects/VertexArray.hh>
#include <glow/objects/TextureCubeMap.hh>
#include <vector>
struct vertex
{
tg::pos3 pos;
tg::vec3 normal;
tg::color3 color;
};
struct mesh
{
std::vector<vertex> vertices;
glow::SharedArrayBuffer arrayBuffer; // vertex data
glow::SharedVertexArray vertexArray; // mesh config
void add_triangle(tg::pos3 v0, tg::pos3 v1, tg::pos3 v2, tg::color3 c)
{
auto n = normalize(cross(v1 - v0, v2 - v0));
vertices.push_back({v0, n, c});
vertices.push_back({v1, n, c});
vertices.push_back({v2, n, c});
}
void upload();
};
struct camera
{
float aspect_ratio = 1.f;
tg::pos3 pos = {8, 3, 8};
tg::dir3 dir = normalize(tg::pos3::zero - pos);
tg::dir3 up = {0, 1, 0};
tg::dir3 right() const { return normalize(cross(dir, up)); }
tg::mat4 proj() const { return tg::perspective_opengl(70_deg, aspect_ratio, 0.1f, 1000.f); }
tg::mat4 view() const { return tg::look_at(pos, dir, tg::vec3::unit_y); }
};
class LiveApp : public glow::glfw::GlfwApp
{
mesh debugMesh;
camera cam;
glow::SharedProgram mShaderMesh;
glow::SharedProgram mShaderTerrain;
glow::SharedTexture2D mHeightMapTexture;
glow::SharedTexture2D mTexAlbedo;
glow::SharedTexture2D mTexAO;
glow::SharedTexture2D mTexNormal;
glow::SharedTexture2D mTexHeight;
glow::SharedTexture2D mTexRoughness;
glow::SharedProgram mShaderOutput;
glow::SharedVertexArray mQuad;
glow::SharedFramebuffer mFramebuffer;
glow::SharedTextureRectangle mTargetColor;
glow::SharedTextureRectangle mTargetDepth;
glow::SharedTextureCubeMap mSkyBox;
int mTerrainSize = 128;
std::vector<float> mHeightMap;
int mViewDistance = 200;
float mEpsMultiplier = 1;
int idxOf(int x, int z) const { return z * mTerrainSize + x; }
bool mKeyDownW = false;
bool mKeyDownA = false;
bool mKeyDownS = false;
bool mKeyDownD = false;
bool mKeyDownSpace = false;
bool mWireframe = false;
float mDepthBelowCursor;
tg::pos3 mWorldPosBelowCursor;
public:
void init() override;
void update(float elapsedSeconds) override;
void render(float elapsedSeconds) override;
void onResize(int w, int h) override;
void onGui() override;
bool onMouseButton(double x, double y, int button, int action, int mods, int clickCount) override;
bool onMousePosition(double x, double y) override;
bool onKey(int key, int scancode, int action, int mods) override;
};
#include "LiveApp.hh"
int main()
{
LiveApp app;
app.run();
}
in vec3 vNormal;
in vec3 vColor;
out vec3 fColor;
void main()
{
fColor = vColor;
}
uniform mat4 uView;
uniform mat4 uProj;
in vec3 aPosition;
in vec3 aNormal;
in vec3 aColor;
out vec3 vColor;
out vec3 vNormal;
void main()
{
vColor = aColor;
vNormal = aNormal;
gl_Position = uProj * uView * vec4(aPosition, 1);
}
uniform sampler2DRect uTargetColor;
uniform sampler2DRect uTargetDepth;
uniform samplerCube uSkyBox;
uniform mat4 uInvProj;
uniform mat4 uInvView;
in vec2 vPosition;
out vec3 fColor;
void main()
{
vec4 near = vec4(vPosition * 2 - 1, -1, 1);
vec4 far = vec4(vPosition * 2 - 1, 1, 1);
near = uInvProj * near;
far = uInvProj * far;
near = uInvView * near;
far = uInvView * far;
near /= near.w;
far /= far.w;
vec3 V = (far - near).xyz;
float d = texture(uTargetDepth, gl_FragCoord.xy).x;
if (d == 1)
fColor = texture(uSkyBox, V).rgb;
else
fColor = texture(uTargetColor, gl_FragCoord.xy).rgb;
fColor = pow(fColor, vec3(0.5));
}
in vec2 aPosition;
out vec2 vPosition;
void main()
{
vPosition = aPosition;
gl_Position = vec4(aPosition * 2 - 1, 0, 1);
}
uniform sampler2D uTexAlbedo;
uniform sampler2D uTexNormal;
uniform sampler2D uTexAO;
uniform sampler2D uTexHeight;
uniform sampler2D uTexRoughness;
uniform samplerCube uSkyBox;
uniform float uEpsMultiplier;
uniform float uRuntime;
uniform vec3 uCamPos;
in vec3 vNormal;
in vec3 vTangent;
in vec3 vBitangent;
in vec3 vColor;
in vec3 vWorldPos;
out vec3 fColor;
void main()
{
vec2 uv = vWorldPos.xz / 5;
float apparentHeight = 0.1;
vec3 N = normalize(vNormal); // vec3(0,1,0);
vec3 T = normalize(vTangent); // vec3(1,0,0);
vec3 B = normalize(vBitangent); // vec3(0,0,-1);
// vec3 lightPos = vec3(4 * cos(uRuntime), 3 + 2 * cos(uRuntime * 0.3), 4 * sin(uRuntime));
// vec3 L = normalize(lightPos - vWorldPos);
vec3 L = vec3(0,1,0);
vec3 V = normalize(uCamPos - vWorldPos);
vec3 albedo = texture(uTexAlbedo, uv).rgb;
float ao = texture(uTexAO, uv).x;
float h = texture(uTexHeight, uv).x;
vec3 normalMap = texture(uTexNormal, uv).rgb;
normalMap.xy = normalMap.xy * 2 - 1;
// fColor = N;
N = normalize(
T * normalMap.x +
B * normalMap.y +
N * normalMap.z
// + N * 215
);
vec3 R = reflect(-V, N);
// fColor = N;
fColor = albedo * ao * max(0, dot(N, L));
// fColor = textureLod(uSkyBox, R, 5).rgb;
fColor += 0.1 * texture(uSkyBox, R).rgb;
// fColor = albedo;
// fColor = vColor * max(0, normalize(vNormal).y);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment