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

live coding 9

parent 268f72aa
No related branches found
No related tags found
No related merge requests found
...@@ -99,11 +99,14 @@ void LiveApp::modifyTerrain(float elapsedSeconds) ...@@ -99,11 +99,14 @@ void LiveApp::modifyTerrain(float elapsedSeconds)
continue; continue;
auto& h = mHeightMap[y * mTerrainSize + x]; auto& h = mHeightMap[y * mTerrainSize + x];
auto& g = mGrassMap[y * mTerrainSize + x];
switch (mEditMode) switch (mEditMode)
{ {
case edit_mode::set_to_zero: case edit_mode::set_to_zero:
h = 0; h = 0;
g.x = 0;
g.y = 1;
break; break;
case edit_mode::add: case edit_mode::add:
h += tg::smoothstep(mModificationRadius, mModificationRadius * 0.5f, d) * elapsedSeconds; h += tg::smoothstep(mModificationRadius, mModificationRadius * 0.5f, d) * elapsedSeconds;
...@@ -114,6 +117,11 @@ void LiveApp::modifyTerrain(float elapsedSeconds) ...@@ -114,6 +117,11 @@ void LiveApp::modifyTerrain(float elapsedSeconds)
h = tg::mix(origH, h, tg::pow(0.5f, elapsedSeconds)); h = tg::mix(origH, h, tg::pow(0.5f, elapsedSeconds));
} }
break; break;
case edit_mode::grow_grass:
g.x = tg::clamp(g.x + elapsedSeconds * 0.5f, 0.0f, 1.0f);
g.z = tg::clamp(g.z - elapsedSeconds * 0.3f, 0.0f, 1.0f);
// g.x = tg::mix(g.x, 1.0f, tg::pow(0.5f, elapsedSeconds));
break;
case edit_mode::random_walk: case edit_mode::random_walk:
h += uniform(rng, -1.f, 1.f) * elapsedSeconds * 10; h += uniform(rng, -1.f, 1.f) * elapsedSeconds * 10;
break; break;
...@@ -121,9 +129,16 @@ void LiveApp::modifyTerrain(float elapsedSeconds) ...@@ -121,9 +129,16 @@ void LiveApp::modifyTerrain(float elapsedSeconds)
} }
// reupload data after modification // reupload data after modification
{
auto tex = mHeightMapTexture->bind(); auto tex = mHeightMapTexture->bind();
tex.setData(GL_R32F, mTerrainSize, mTerrainSize, mHeightMap); tex.setData(GL_R32F, mTerrainSize, mTerrainSize, mHeightMap);
tex.generateMipmaps(); tex.generateMipmaps();
}
{
auto tex = mGrassMapTexture->bind();
tex.setData(GL_RGB32F, mTerrainSize, mTerrainSize, mGrassMap);
tex.generateMipmaps();
}
auto end = std::chrono::high_resolution_clock::now(); auto end = std::chrono::high_resolution_clock::now();
glow::info() << "terrain modified in " << std::chrono::duration<double>(end - start).count() * 1000 << " ms"; glow::info() << "terrain modified in " << std::chrono::duration<double>(end - start).count() * 1000 << " ms";
...@@ -140,6 +155,7 @@ void LiveApp::init() ...@@ -140,6 +155,7 @@ void LiveApp::init()
mShaderMesh = glow::Program::createFromFile(src_folder + "/mesh"); mShaderMesh = glow::Program::createFromFile(src_folder + "/mesh");
mShaderTerrain = glow::Program::createFromFile(src_folder + "/terrain"); mShaderTerrain = glow::Program::createFromFile(src_folder + "/terrain");
mShaderOutput = glow::Program::createFromFile(src_folder + "/output"); mShaderOutput = glow::Program::createFromFile(src_folder + "/output");
mShaderGrass = glow::Program::createFromFile(src_folder + "/grass");
mSkyBox = glow::TextureCubeMap::createFromData(glow::TextureData::createFromFileCube( // mSkyBox = glow::TextureCubeMap::createFromData(glow::TextureData::createFromFileCube( //
src_folder + "/../../textures/posx.jpg", // src_folder + "/../../textures/posx.jpg", //
...@@ -166,10 +182,14 @@ void LiveApp::init() ...@@ -166,10 +182,14 @@ void LiveApp::init()
{ {
tg::rng rng; tg::rng rng;
mHeightMap.resize(mTerrainSize * mTerrainSize); mHeightMap.resize(mTerrainSize * mTerrainSize);
mGrassMap.resize(mTerrainSize * mTerrainSize);
for (auto z = 0; z < mTerrainSize; ++z) for (auto z = 0; z < mTerrainSize; ++z)
for (auto x = 0; x < mTerrainSize; ++x) for (auto x = 0; x < mTerrainSize; ++x)
{ {
mHeightMap[idxOf(x, z)] = sampleTerrainAt(x, z, mTerrainSize); mHeightMap[idxOf(x, z)] = sampleTerrainAt(x, z, mTerrainSize);
float density = 0.5f + 0.5f * tg::cos(10_deg * x);
float length = 1.0f + 0.5f * tg::cos(10_deg * z);
mGrassMap[idxOf(x, z)] = {density, length, 1.f};
} }
mHeightMapTexture = glow::Texture2D::create(); mHeightMapTexture = glow::Texture2D::create();
...@@ -179,6 +199,13 @@ void LiveApp::init() ...@@ -179,6 +199,13 @@ void LiveApp::init()
tex.setWrap(GL_REPEAT, GL_REPEAT); tex.setWrap(GL_REPEAT, GL_REPEAT);
tex.generateMipmaps(); tex.generateMipmaps();
} }
mGrassMapTexture = glow::Texture2D::create();
{
auto tex = mGrassMapTexture->bind();
tex.setData(GL_RGB32F, mTerrainSize, mTerrainSize, mGrassMap);
tex.setWrap(GL_REPEAT, GL_REPEAT);
tex.generateMipmaps();
}
if (false) // old terrain if (false) // old terrain
for (auto z = 0; z < mTerrainSize - 1; ++z) for (auto z = 0; z < mTerrainSize - 1; ++z)
...@@ -199,6 +226,38 @@ void LiveApp::init() ...@@ -199,6 +226,38 @@ void LiveApp::init()
} }
} }
// init grass geometry
{
auto grass_segments = 3;
std::vector<tg::pos2> grass_vertices;
grass_vertices.resize(1 + 2 * grass_segments);
grass_vertices[0] = {.5f, 1.f};
for (auto i = 0; i < grass_segments; ++i)
{
grass_vertices[1 + i * 2 + 0] = {0.f, 1 - (i + 1.f) / grass_segments};
grass_vertices[1 + i * 2 + 1] = {1.f, 1 - (i + 1.f) / grass_segments};
}
std::reverse(grass_vertices.begin(), grass_vertices.end());
auto ab_grass = glow::ArrayBuffer::create();
ab_grass->defineAttribute<tg::pos2>("aGrassPos");
ab_grass->setDivisor(0);
ab_grass->bind().setData(grass_vertices);
tg::rng rng;
std::vector<tg::pos2> seeds;
auto bb = tg::aabb2(0, mTerrainSize);
for (auto i = 0; i < 1'000'000; ++i)
seeds.push_back(uniform(rng, bb));
auto ab_seed = glow::ArrayBuffer::create();
ab_seed->defineAttribute<tg::pos2>("aSeedPos");
ab_seed->setDivisor(1);
ab_seed->bind().setData(seeds);
mMeshGrass = glow::VertexArray::create({ab_seed, ab_grass}, nullptr, GL_TRIANGLE_STRIP);
glow::info() << "grass mesh with " << mMeshGrass->getInstanceCount() << " instances";
}
auto c = tg::pos3(0, 1, 0); auto c = tg::pos3(0, 1, 0);
auto dx = tg::vec3::unit_x; auto dx = tg::vec3::unit_x;
auto dy = tg::vec3::unit_y; auto dy = tg::vec3::unit_y;
...@@ -271,6 +330,7 @@ void LiveApp::render(float elapsedSeconds) ...@@ -271,6 +330,7 @@ void LiveApp::render(float elapsedSeconds)
shader["uTerrainSize"] = mTerrainSize; shader["uTerrainSize"] = mTerrainSize;
shader["uViewDistance"] = mViewDistance; shader["uViewDistance"] = mViewDistance;
shader["uHeightMap"] = mHeightMapTexture; shader["uHeightMap"] = mHeightMapTexture;
shader["uGrassMap"] = mGrassMapTexture;
shader["uCenterPos"] = tg::round(cam.pos); shader["uCenterPos"] = tg::round(cam.pos);
shader["uCamPos"] = cam.pos; shader["uCamPos"] = cam.pos;
...@@ -291,6 +351,26 @@ void LiveApp::render(float elapsedSeconds) ...@@ -291,6 +351,26 @@ void LiveApp::render(float elapsedSeconds)
mQuad->bind().draw(mViewDistance * mViewDistance); mQuad->bind().draw(mViewDistance * mViewDistance);
} }
// render grass
{
GLOW_SCOPED(disable, GL_CULL_FACE);
auto shader = mShaderGrass->use();
shader["uProj"] = proj;
shader["uView"] = view;
shader["uTerrainSize"] = mTerrainSize;
shader["uViewDistance"] = mViewDistance;
shader["uHeightMap"] = mHeightMapTexture;
shader["uGrassMap"] = mGrassMapTexture;
shader["uCenterPos"] = tg::round(cam.pos);
shader["uCamPos"] = cam.pos;
shader["uRuntime"] = (float)glfwGetTime();
mMeshGrass->bind().draw();
}
} }
// read back screen pixel // read back screen pixel
...@@ -365,6 +445,8 @@ void LiveApp::onGui() ...@@ -365,6 +445,8 @@ void LiveApp::onGui()
mEditMode = edit_mode::reset; mEditMode = edit_mode::reset;
if (ImGui::RadioButton("edit: random walk", mEditMode == edit_mode::random_walk)) if (ImGui::RadioButton("edit: random walk", mEditMode == edit_mode::random_walk))
mEditMode = edit_mode::random_walk; mEditMode = edit_mode::random_walk;
if (ImGui::RadioButton("edit: grow grass", mEditMode == edit_mode::grow_grass))
mEditMode = edit_mode::grow_grass;
} }
ImGui::End(); ImGui::End();
} }
......
...@@ -54,7 +54,8 @@ enum class edit_mode ...@@ -54,7 +54,8 @@ enum class edit_mode
set_to_zero, set_to_zero,
add, add,
reset, reset,
random_walk random_walk,
grow_grass,
}; };
class LiveApp : public glow::glfw::GlfwApp class LiveApp : public glow::glfw::GlfwApp
...@@ -65,7 +66,11 @@ class LiveApp : public glow::glfw::GlfwApp ...@@ -65,7 +66,11 @@ class LiveApp : public glow::glfw::GlfwApp
glow::SharedProgram mShaderMesh; glow::SharedProgram mShaderMesh;
glow::SharedProgram mShaderTerrain; glow::SharedProgram mShaderTerrain;
glow::SharedProgram mShaderGrass;
glow::SharedVertexArray mMeshGrass;
glow::SharedTexture2D mHeightMapTexture; glow::SharedTexture2D mHeightMapTexture;
glow::SharedTexture2D mGrassMapTexture;
glow::SharedTexture2D mTexAlbedo; glow::SharedTexture2D mTexAlbedo;
glow::SharedTexture2D mTexAO; glow::SharedTexture2D mTexAO;
...@@ -84,6 +89,7 @@ class LiveApp : public glow::glfw::GlfwApp ...@@ -84,6 +89,7 @@ class LiveApp : public glow::glfw::GlfwApp
int mTerrainSize = 128; int mTerrainSize = 128;
std::vector<float> mHeightMap; std::vector<float> mHeightMap;
std::vector<tg::pos3> mGrassMap;
int mViewDistance = 200; int mViewDistance = 200;
......
in vec2 vGrassPos;
in vec3 vBaseColor;
out vec3 fColor;
void main()
{
fColor = vBaseColor * vGrassPos.y * vGrassPos.y;
}
uniform sampler2D uHeightMap;
uniform sampler2D uGrassMap;
uniform int uTerrainSize;
uniform int uViewDistance;
uniform vec3 uCenterPos;
uniform mat4 uView;
uniform mat4 uProj;
uniform float uRuntime;
in vec2 aGrassPos;
in vec2 aSeedPos;
out vec3 vBaseColor;
out vec3 vWorldPos;
out vec2 vGrassPos;
vec2 windAt(float x, float z)
{
return vec2(0.5,0.5) * (cos(x / 6.2 + z / 10.123 + uRuntime) + 0.3 * cos(x / -2.3 + z / 4.3 + uRuntime * 2));
}
vec3 worldPosAt(float x, float z)
{
vec3 p;
p.x = x;
p.y = texture(uHeightMap, vec2(x, z) / uTerrainSize).x;
p.y *= 3;
p.z = z;
return p;
}
void main()
{
vGrassPos = aGrassPos;
vec3 pos;
pos = worldPosAt(aSeedPos.x, aSeedPos.y);
vec3 grass_data = texture(uGrassMap, aSeedPos / uTerrainSize).xyz;
float grass_alpha = 0.5 + 0.5 * cos(312.2 * gl_InstanceID);
if (grass_alpha >= grass_data.x)
{
gl_Position = vec4(0,0,0,0);
return;
}
float size = smoothstep(grass_data.x, max(0.f, grass_data.x - .2f), grass_alpha);
vBaseColor = vec3(0);
vBaseColor = mix(vec3(1,0,0), vec3(0,1,0), grass_data.z);
vBaseColor.g += 0.4f * cos(842.13 * gl_InstanceID);
vBaseColor.r += 0.4f * cos(-642.13 * gl_InstanceID);
vBaseColor = clamp(vBaseColor, vec3(0), vec3(1));
float a = 123.134 * gl_InstanceID;
float sa = sin(a);
float ca = cos(a);
float w = 0.2f;
float l = 1.5f;
w += 0.05f * cos(7123.2 * gl_InstanceID);
l += 0.25f * cos(1723.2 * gl_InstanceID);
float c = 0.8f;
c += 0.4 * cos(523.2 * gl_InstanceID);
vec2 right = vec2(sa, ca);
vec2 front = vec2(-ca, sa);
pos.y += size * aGrassPos.y * l * grass_data.y;
pos.xz += size * right * (aGrassPos.x - 0.5) * w;
pos.xz += size * c * front * aGrassPos.y * aGrassPos.y;
pos.xz += size * windAt(aSeedPos.x, aSeedPos.y) * aGrassPos.y;
vWorldPos = pos;
gl_Position = uProj * uView * vec4(vWorldPos, 1);
}
...@@ -60,6 +60,8 @@ void main() ...@@ -60,6 +60,8 @@ void main()
fColor += 0.1 * texture(uSkyBox, R).rgb; fColor += 0.1 * texture(uSkyBox, R).rgb;
// fColor = albedo; // fColor = albedo;
fColor *= vColor;
float d = distance(uCursorPos.xz, vWorldPos.xz); float d = distance(uCursorPos.xz, vWorldPos.xz);
if (d < 0.1) if (d < 0.1)
......
uniform sampler2D uHeightMap;
uniform sampler2D uGrassMap;
uniform int uTerrainSize;
uniform int uViewDistance;
uniform vec3 uCenterPos;
uniform mat4 uView;
uniform mat4 uProj;
in vec2 aPosition;
out vec3 vWorldPos;
out vec3 vNormal;
out vec3 vTangent;
out vec3 vBitangent;
out vec3 vColor;
vec3 worldPosAt(float x, float z)
{
vec3 p;
p.x = x;
p.y = texture(uHeightMap, vec2(x, z) / uTerrainSize).x;
p.y *= 3;
p.z = z;
return p;
}
void main()
{
int ix = gl_InstanceID % uViewDistance;
int iz = gl_InstanceID / uViewDistance;
float wx = ix - uViewDistance / 2 + uCenterPos.x + aPosition.x;
float wz = iz - uViewDistance / 2 + uCenterPos.z + aPosition.y;
vWorldPos = worldPosAt(wx, wz);
vec3 grass_data = texture(uGrassMap, vec2(wx, wz) / uTerrainSize).xyz;
vec3 p_pos_x = worldPosAt(wx + 1, wz);
vec3 p_neg_x = worldPosAt(wx - 1, wz);
vec3 p_pos_z = worldPosAt(wx, wz + 1);
vec3 p_neg_z = worldPosAt(wx, wz - 1);
vNormal = -normalize(cross(p_pos_x - p_neg_x, p_pos_z - p_neg_z));
vTangent = normalize(p_pos_x - p_neg_x);
vBitangent = normalize(p_pos_z - p_neg_z);
vColor = vec3(1,1,1);
vColor *= 1 - smoothstep(0.0, 0.5, grass_data.x);
gl_Position = uProj * uView * vec4(vWorldPos, 1);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment