@@ -78,6 +78,7 @@ tools/make-font | |||
tutorial/01_triangle | |||
tutorial/02_cube | |||
tutorial/03_noise | |||
tutorial/04_texture | |||
tutorial/05_easymesh | |||
tutorial/08_fbo | |||
tutorial/11_fractal | |||
@@ -50,6 +50,7 @@ struct ShaderTexture | |||
{ | |||
friend class Shader; | |||
friend class FrameBuffer; | |||
friend class Texture; | |||
public: | |||
inline ShaderTexture() : m_flags(0) {} | |||
@@ -45,11 +45,11 @@ class TextureData | |||
PixelFormat m_format; | |||
#if defined USE_D3D9 | |||
IDirect3DTexture9 *m_tex; | |||
IDirect3DTexture9 *m_texture; | |||
#elif defined _XBOX | |||
D3DTexture *m_tex; | |||
D3DTexture *m_texture; | |||
#else | |||
GLuint m_texid; | |||
GLuint m_texture; | |||
GLint m_internal_format; | |||
GLenum m_gl_format, m_gl_type; | |||
#endif | |||
@@ -101,7 +101,7 @@ Texture::Texture(ivec2 size, PixelFormat format) | |||
g_d3ddevice->CreateTexture(m_data->m_size.x, m_data->m_size.y, 1, | |||
d3d_usage, d3d_format, | |||
D3DPOOL_DEFAULT, &m_data->m_tex, NULL); | |||
D3DPOOL_DEFAULT, &m_data->m_texture, NULL); | |||
#else | |||
static struct | |||
{ | |||
@@ -143,8 +143,8 @@ Texture::Texture(ivec2 size, PixelFormat format) | |||
m_data->m_gl_format = GET_CLAMPED(gl_formats, format).format; | |||
m_data->m_gl_type = GET_CLAMPED(gl_formats, format).type; | |||
glGenTextures(1, &m_data->m_texid); | |||
glBindTexture(GL_TEXTURE_2D, m_data->m_texid); | |||
glGenTextures(1, &m_data->m_texture); | |||
glBindTexture(GL_TEXTURE_2D, m_data->m_texture); | |||
# if defined __CELLOS_LV2__ | |||
/* We need this hint because by default the storage type is | |||
@@ -157,15 +157,26 @@ Texture::Texture(ivec2 size, PixelFormat format) | |||
#endif | |||
} | |||
ShaderTexture Texture::GetTexture() const | |||
{ | |||
ShaderTexture ret; | |||
#if defined USE_D3D9 || defined _XBOX | |||
ret.m_flags = (uint64_t)(uintptr_t)m_data->m_texture; | |||
#else | |||
ret.m_flags = m_data->m_texture; | |||
#endif | |||
return ret; | |||
} | |||
void Texture::Bind() | |||
{ | |||
#if defined _XBOX || defined USE_D3D9 | |||
g_d3ddevice->SetTexture(0, m_data->m_tex); | |||
g_d3ddevice->SetTexture(0, m_data->m_texture); | |||
#else | |||
# if !defined HAVE_GLES_2X | |||
glEnable(GL_TEXTURE_2D); | |||
# endif | |||
glBindTexture(GL_TEXTURE_2D, m_data->m_texid); | |||
glBindTexture(GL_TEXTURE_2D, m_data->m_texture); | |||
#endif | |||
} | |||
@@ -174,14 +185,14 @@ void Texture::SetData(void *data) | |||
#if defined _XBOX || defined USE_D3D9 | |||
D3DLOCKED_RECT rect; | |||
# if defined USE_D3D9 | |||
m_data->m_tex->LockRect(0, &rect, NULL, D3DLOCK_DISCARD); | |||
m_data->m_texture->LockRect(0, &rect, NULL, D3DLOCK_DISCARD); | |||
# else | |||
m_data->m_tex->LockRect(0, &rect, NULL, 0); | |||
m_data->m_texture->LockRect(0, &rect, NULL, 0); | |||
# endif | |||
memcpy(rect.pBits, data, rect.Pitch * m_data->m_size.y); | |||
m_data->m_tex->UnlockRect(0); | |||
m_data->m_texture->UnlockRect(0); | |||
#else | |||
glTexImage2D(GL_TEXTURE_2D, 0, m_data->m_internal_format, | |||
@@ -194,7 +205,7 @@ void Texture::SetSubData(ivec2 origin, ivec2 size, void *data) | |||
{ | |||
#if defined _XBOX || defined USE_D3D9 | |||
D3DLOCKED_RECT rect; | |||
m_data->m_tex->LockRect(0, &rect, NULL, 0); | |||
m_data->m_texture->LockRect(0, &rect, NULL, 0); | |||
for (int j = 0; j < size.y; j++) | |||
{ | |||
@@ -204,7 +215,7 @@ void Texture::SetSubData(ivec2 origin, ivec2 size, void *data) | |||
memcpy(dst, src, size.x * 4); | |||
} | |||
m_data->m_tex->UnlockRect(0); | |||
m_data->m_texture->UnlockRect(0); | |||
#else | |||
glTexSubImage2D(GL_TEXTURE_2D, 0, origin.x, origin.y, size.x, size.y, | |||
@@ -215,9 +226,9 @@ void Texture::SetSubData(ivec2 origin, ivec2 size, void *data) | |||
Texture::~Texture() | |||
{ | |||
#if defined USE_D3D9 || defined _XBOX | |||
m_data->m_tex->Release(); | |||
m_data->m_texture->Release(); | |||
#else | |||
glDeleteTextures(1, &m_data->m_texid); | |||
glDeleteTextures(1, &m_data->m_texture); | |||
#endif | |||
delete m_data; | |||
@@ -46,6 +46,8 @@ public: | |||
void SetData(void *data); | |||
void SetSubData(ivec2 origin, ivec2 size, void *data); | |||
ShaderTexture GetTexture() const; | |||
private: | |||
class TextureData *m_data; | |||
}; | |||
@@ -0,0 +1,156 @@ | |||
// | |||
// Lol Engine - Noise tutorial | |||
// | |||
// Copyright: (c) 2012 Sam Hocevar <sam@hocevar.net> | |||
// This program is free software; you can redistribute it and/or | |||
// modify it under the terms of the Do What The Fuck You Want To | |||
// Public License, Version 2, as published by Sam Hocevar. See | |||
// http://sam.zoy.org/projects/COPYING.WTFPL for more details. | |||
// | |||
#if defined HAVE_CONFIG_H | |||
# include "config.h" | |||
#endif | |||
#include "core.h" | |||
#include "loldebug.h" | |||
using namespace std; | |||
using namespace lol; | |||
extern char const *lolfx_04_texture; | |||
class TextureDemo : public WorldEntity | |||
{ | |||
public: | |||
TextureDemo() : | |||
m_frames(0), | |||
m_ready(false) | |||
{ | |||
m_vertices << vec2(-1.0, 1.0); | |||
m_vertices << vec2(-1.0, -1.0); | |||
m_vertices << vec2( 1.0, -1.0); | |||
m_vertices << vec2(-1.0, 1.0); | |||
m_vertices << vec2( 1.0, -1.0); | |||
m_vertices << vec2( 1.0, 1.0); | |||
m_heightmap = new uint8_t[4 * 512 * 1]; | |||
} | |||
virtual ~TextureDemo() | |||
{ | |||
delete m_heightmap; | |||
} | |||
virtual void TickGame(float seconds) | |||
{ | |||
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)); | |||
} | |||
} | |||
/* Slightly disturb the terrain */ | |||
for (int i = 1; i < 511; i++) | |||
{ | |||
int delta = (rand() & 1) ? 1 : -1; | |||
if (rand() & 3) | |||
continue; | |||
uint8_t ¢er = 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++; | |||
} | |||
} | |||
/* Update frame counter */ | |||
++m_frames; | |||
} | |||
virtual void TickDraw(float seconds) | |||
{ | |||
WorldEntity::TickDraw(seconds); | |||
/* Initialise GPU data */ | |||
if (!m_ready) | |||
{ | |||
m_texture = new Texture(ivec2(512, 1), PixelFormat::A8R8G8B8); | |||
m_shader = Shader::Create(lolfx_04_texture); | |||
m_coord = m_shader->GetAttribLocation("in_Position", VertexUsage::Position, 0); | |||
m_vdecl = new VertexDeclaration(VertexStream<vec2>(VertexUsage::Position)); | |||
m_vbo = new VertexBuffer(m_vertices.Bytes()); | |||
void *vertices = m_vbo->Lock(0, 0); | |||
memcpy(vertices, &m_vertices[0], m_vertices.Bytes()); | |||
m_vbo->Unlock(); | |||
m_ready = true; | |||
/* FIXME: this object never cleans up */ | |||
} | |||
/* Send new heightmap to GPU */ | |||
m_texture->SetData(m_heightmap); | |||
m_shader->Bind(); | |||
m_shader->SetUniform(m_texture_uni, m_texture->GetTexture(), 0); | |||
m_vdecl->SetStream(m_vbo, m_coord); | |||
m_vdecl->Bind(); | |||
m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6); | |||
m_vdecl->Unbind(); | |||
} | |||
private: | |||
Array<vec2> m_vertices; | |||
Texture *m_texture; | |||
Shader *m_shader; | |||
ShaderAttrib m_coord; | |||
ShaderUniform m_texture_uni; | |||
VertexDeclaration *m_vdecl; | |||
VertexBuffer *m_vbo; | |||
uint8_t *m_heightmap; | |||
int m_frames; | |||
bool m_ready; | |||
}; | |||
int main(int argc, char **argv) | |||
{ | |||
Application app("Tutorial 4: Texture", ivec2(640, 480), 60.0f); | |||
#if defined _MSC_VER && !defined _XBOX | |||
_chdir("../.."); | |||
#elif defined _WIN32 && !defined _XBOX | |||
_chdir("../.."); | |||
#endif | |||
new TextureDemo(); | |||
app.Run(); | |||
return EXIT_SUCCESS; | |||
} | |||
@@ -0,0 +1,64 @@ | |||
[vert.glsl] | |||
#version 120 | |||
attribute vec2 in_Position; | |||
varying vec4 pass_Position; | |||
void main(void) | |||
{ | |||
pass_Position = vec4(0.5 * in_Position + 0.5, 0.0, 1.0); | |||
gl_Position = vec4(in_Position, 0.0, 1.0); | |||
} | |||
[frag.glsl] | |||
#version 120 | |||
uniform sampler2D u_Texture; | |||
varying vec4 pass_Position; | |||
float rand(in vec2 p, in float v) | |||
{ | |||
return fract(v * sin(dot(p, vec2(1298.9837, 7823.33145)))); | |||
} | |||
void main(void) | |||
{ | |||
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.02) | |||
{ | |||
/* 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); | |||
} | |||
} | |||
@@ -0,0 +1,68 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
<ItemGroup Label="ProjectConfigurations"> | |||
<ProjectConfiguration Include="Debug|PS3"> | |||
<Configuration>Debug</Configuration> | |||
<Platform>PS3</Platform> | |||
</ProjectConfiguration> | |||
<ProjectConfiguration Include="Debug|Win32"> | |||
<Configuration>Debug</Configuration> | |||
<Platform>Win32</Platform> | |||
</ProjectConfiguration> | |||
<ProjectConfiguration Include="Debug|x64"> | |||
<Configuration>Debug</Configuration> | |||
<Platform>x64</Platform> | |||
</ProjectConfiguration> | |||
<ProjectConfiguration Include="Debug|Xbox 360"> | |||
<Configuration>Debug</Configuration> | |||
<Platform>Xbox 360</Platform> | |||
</ProjectConfiguration> | |||
<ProjectConfiguration Include="Release|PS3"> | |||
<Configuration>Release</Configuration> | |||
<Platform>PS3</Platform> | |||
</ProjectConfiguration> | |||
<ProjectConfiguration Include="Release|Win32"> | |||
<Configuration>Release</Configuration> | |||
<Platform>Win32</Platform> | |||
</ProjectConfiguration> | |||
<ProjectConfiguration Include="Release|x64"> | |||
<Configuration>Release</Configuration> | |||
<Platform>x64</Platform> | |||
</ProjectConfiguration> | |||
<ProjectConfiguration Include="Release|Xbox 360"> | |||
<Configuration>Release</Configuration> | |||
<Platform>Xbox 360</Platform> | |||
</ProjectConfiguration> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ClCompile Include="04_texture.cpp" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<LolFxCompile Include="04_texture.lolfx" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="$(SolutionDir)\..\..\src\lolcore.vcxproj"> | |||
<Project>{9e62f2fe-3408-4eae-8238-fd84238ceeda}</Project> | |||
</ProjectReference> | |||
</ItemGroup> | |||
<PropertyGroup Label="Globals"> | |||
<ProjectGuid>{834852db-edb6-4fd0-bcf9-45cd01126962}</ProjectGuid> | |||
<ConfigurationType>Application</ConfigurationType> | |||
<Keyword>Win32Proj</Keyword> | |||
</PropertyGroup> | |||
<Import Project="$(SolutionDir)\Lol.Core.Config.props" /> | |||
<ImportGroup Label="ExtensionSettings"> | |||
<Import Project="$(SolutionDir)\Lol.Fx.props" /> | |||
</ImportGroup> | |||
<ImportGroup Label="PropertySheets"> | |||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |||
<Import Project="$(SolutionDir)\Lol.Core.Vars.props" /> | |||
</ImportGroup> | |||
<PropertyGroup Label="UserMacros" /> | |||
<Import Project="$(SolutionDir)\Lol.Core.Rules.props" /> | |||
<ItemDefinitionGroup /> | |||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | |||
<ImportGroup Label="ExtensionTargets"> | |||
<Import Project="$(SolutionDir)\Lol.Fx.targets" /> | |||
</ImportGroup> | |||
</Project> |
@@ -3,7 +3,8 @@ include $(top_srcdir)/build/autotools/common.am | |||
AM_CPPFLAGS = -I$(top_srcdir)/src | |||
noinst_PROGRAMS = 01_triangle 02_cube 03_noise 05_easymesh 08_fbo 11_fractal | |||
noinst_PROGRAMS = 01_triangle 02_cube 03_noise 04_texture 05_easymesh \ | |||
08_fbo 11_fractal | |||
01_triangle_SOURCES = 01_triangle.cpp 01_triangle.lolfx | |||
01_triangle_CPPFLAGS = @LOL_CFLAGS@ @PIPI_CFLAGS@ | |||
@@ -20,6 +21,11 @@ noinst_PROGRAMS = 01_triangle 02_cube 03_noise 05_easymesh 08_fbo 11_fractal | |||
03_noise_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@ | |||
03_noise_DEPENDENCIES = $(top_builddir)/src/liblol.a | |||
04_texture_SOURCES = 04_texture.cpp 04_texture.lolfx | |||
04_texture_CPPFLAGS = @LOL_CFLAGS@ @PIPI_CFLAGS@ | |||
04_texture_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@ | |||
04_texture_DEPENDENCIES = $(top_builddir)/src/liblol.a | |||
05_easymesh_SOURCES = 05_easymesh.cpp | |||
05_easymesh_CPPFLAGS = @LOL_CFLAGS@ @PIPI_CFLAGS@ | |||
05_easymesh_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@ | |||