Parcourir la source

tutorial: change the terrain drawing into an antialiased line graph.

legacy
Sam Hocevar sam il y a 12 ans
Parent
révision
8b35c75918
2 fichiers modifiés avec 64 ajouts et 73 suppressions
  1. +16
    -41
      tutorial/04_texture.cpp
  2. +48
    -32
      tutorial/04_texture.lolfx

+ 16
- 41
tutorial/04_texture.cpp Voir le fichier

@@ -1,5 +1,5 @@
//
// Lol Engine - Noise tutorial
// Lol Engine - Graphing tutorial
//
// Copyright: (c) 2012 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
@@ -18,6 +18,8 @@
using namespace std;
using namespace lol;

static int const TEXTURE_WIDTH = 128;

extern char const *lolfx_04_texture;

class TextureDemo : public WorldEntity
@@ -34,7 +36,7 @@ public:
m_vertices << vec2( 1.0, -1.0);
m_vertices << vec2( 1.0, 1.0);

m_heightmap = new uint8_t[4 * 512 * 1];
m_heightmap = new uint8_t[4 * TEXTURE_WIDTH * 1];
}

virtual ~TextureDemo()
@@ -46,45 +48,18 @@ public:
{
WorldEntity::TickGame(seconds);

/* Generate a new heightmap every 400 frames */
if (m_frames % 400 == 0)
{
for (int i = 0, height = 64; i < 512; i++)
{
m_heightmap[4 * i] = height;
m_heightmap[4 * i + 1] = 255; /* unused */
m_heightmap[4 * i + 2] = 255; /* unused */
m_heightmap[4 * i + 3] = 255; /* unused */
height += rand() % 17 - 8;
height += rand() % 17 - 8;
height = std::max(15, std::min(height, 240));
}
}
/* Generate a new heightmap at the beginning */
if (m_frames == 0)
memset(m_heightmap, 255, 4 * TEXTURE_WIDTH);

/* Slightly disturb the terrain */
for (int i = 1; i < 511; i++)
{
int delta = (rand() & 1) ? 1 : -1;

if (rand() & 3)
continue;

uint8_t &center = m_heightmap[4 * i];
uint8_t &side1 = m_heightmap[4 * (i - delta)];
uint8_t &side2 = m_heightmap[4 * (i + delta)];

if (center > side1)
{
center--;
side1++;
}
else if (center > side2)
{
center--;
side2++;
}
}
/* Scroll left */
for (int i = 0; i < TEXTURE_WIDTH - 1; i++)
m_heightmap[4 * i] = m_heightmap[4 * i + 4];

int height = m_heightmap[4 * (TEXTURE_WIDTH - 1)];
height = height / 2 + 255 / 4 + rand() % 97 - 48;
height = std::max(15, std::min(height, 240));
m_heightmap[4 * (TEXTURE_WIDTH - 1)] = height;

/* Update frame counter */
++m_frames;
@@ -97,7 +72,7 @@ public:
/* Initialise GPU data */
if (!m_ready)
{
m_texture = new Texture(ivec2(512, 1), PixelFormat::A8R8G8B8);
m_texture = new Texture(ivec2(TEXTURE_WIDTH, 1), PixelFormat::A8R8G8B8);

m_shader = Shader::Create(lolfx_04_texture);
m_coord = m_shader->GetAttribLocation("in_Position", VertexUsage::Position, 0);


+ 48
- 32
tutorial/04_texture.lolfx Voir le fichier

@@ -25,40 +25,56 @@ float rand(in vec2 p, in float v)
return fract(v * sin(dot(p, vec2(1298.9837, 7823.33145))));
}

float point2segment(vec2 p1, vec2 p2, vec2 a)
{
float l2 = dot(p2 - p1, p2 - p1);
if (l2 == 0.0)
return distance(a, p1);
float t = dot(a - p1, p2 - p1) / l2;
if (t < 0.0)
return distance(a, p1);
else if (t > 1.0)
return distance(a, p2);
vec2 proj = p1 + t * (p2 - p1);
return distance(a, proj);
}


void main(void)
{
float width = 800.0;
float height = 600.0;
float line_width = 2.0;

vec2 t = pass_Position.xy;
vec4 c0 = texture2D(u_Texture, t);
float f = rand(pass_Position.xy, 12345.67);

if (t.y > c0.x)
{
/* Sky */
float val = min(t.y * 2.0, 1.0);
if (f > 0.999)
gl_FragColor = vec4(1.0);
else
gl_FragColor = vec4(0.4, t.y, val, 1.0);
}
else if (t.y > c0.x - 0.03)
{
/* Grass */
if (f > 0.99)
gl_FragColor = vec4(0.4, 0.7, 0.3, 1.0);
else if (f > 0.9)
gl_FragColor = vec4(0.3, 0.6, 0.2, 1.0);
else
gl_FragColor = vec4(0.2, 0.5, 0.1, 1.0);
}
else
{
/* Earth */
if (f > 0.99)
gl_FragColor = vec4(0.7, 0.4, 0.3, 1.0);
else if (f > 0.9)
gl_FragColor = vec4(0.6, 0.3, 0.2, 1.0);
else
gl_FragColor = vec4(0.5, 0.2, 0.1, 1.0);
}
vec2 tc1 = floor(t * 128.0) / 128.0;
vec2 tc2 = tc1 + vec2(1.0, 1.0) / 128.0;
vec2 tc0 = tc1 - vec2(1.0, 1.0) / 128.0;
vec2 tc3 = tc2 + vec2(1.0, 1.0) / 128.0;

float c0 = texture2D(u_Texture, tc0).x;
float c1 = texture2D(u_Texture, tc1).x;
float c2 = texture2D(u_Texture, tc2).x;
float c3 = texture2D(u_Texture, tc3).x;

/* Artificially compress in Y */
c0 *= 0.3;
c1 *= 0.3;
c2 *= 0.3;
c3 *= 0.3;

vec2 p0 = vec2(tc0.x * width, c0 * height);
vec2 p1 = vec2(tc1.x * width, c1 * height);
vec2 p2 = vec2(tc2.x * width, c2 * height);
vec2 p3 = vec2(tc3.x * width, c3 * height);
vec2 a = vec2(t.x * width, t.y * height);

float d0 = point2segment(p0, p1, a);
float d1 = point2segment(p1, p2, a);
float d2 = point2segment(p2, p3, a);

float d = clamp(line_width - min(min(d0, d1), d2), 0.0, 1.0);

gl_FragColor = vec4(t.y, d, d * 0.3, 1.0);
}


Chargement…
Annuler
Enregistrer