Browse Source

easymesh: interface the shiny shader with new Light objects.

legacy
Sam Hocevar sam 13 years ago
parent
commit
0ba4e6d9e0
13 changed files with 233 additions and 67 deletions
  1. +1
    -0
      src/Makefile.am
  2. +1
    -0
      src/core.h
  3. +12
    -0
      src/easymesh/easymesh.cpp
  4. +1
    -1
      src/easymesh/easymesh.h
  5. +39
    -48
      src/easymesh/shiny.lolfx
  6. +1
    -0
      src/entity.h
  7. +71
    -0
      src/light.cpp
  8. +50
    -0
      src/light.h
  9. +2
    -0
      src/lolcore.vcxproj
  10. +6
    -0
      src/lolcore.vcxproj.filters
  11. +30
    -18
      src/scene.cpp
  12. +4
    -0
      src/scene.h
  13. +15
    -0
      tutorial/05_easymesh.cpp

+ 1
- 0
src/Makefile.am View File

@@ -14,6 +14,7 @@ liblol_a_SOURCES = \
profiler.cpp profiler.h text.cpp text.h emitter.cpp emitter.h numeric.h \ profiler.cpp profiler.h text.cpp text.h emitter.cpp emitter.h numeric.h \
worldentity.cpp worldentity.h gradient.cpp gradient.h gradient.lolfx \ worldentity.cpp worldentity.h gradient.cpp gradient.h gradient.lolfx \
platform.cpp platform.h sprite.cpp sprite.h camera.cpp camera.h \ platform.cpp platform.h sprite.cpp sprite.h camera.cpp camera.h \
light.cpp light.h \
\ \
lol/base/log.h lol/base/array.h lol/base/types.h lol/base/array.h \ lol/base/log.h lol/base/array.h lol/base/types.h lol/base/array.h \
lol/base/string.h lol/base/hash.h lol/base/map.h \ lol/base/string.h lol/base/hash.h lol/base/map.h \


+ 1
- 0
src/core.h View File

@@ -116,6 +116,7 @@ static inline int isnan(float f)
#include "worldentity.h" #include "worldentity.h"


#include "camera.h" #include "camera.h"
#include "light.h"
#include "emitter.h" #include "emitter.h"
#include "font.h" #include "font.h"
#include "gradient.h" #include "gradient.h"


+ 12
- 0
src/easymesh/easymesh.cpp View File

@@ -79,6 +79,7 @@ void EasyMesh::MeshConvert(Shader* provided_shader)
m_gpu.proj = m_gpu.shader->GetUniformLocation("in_Proj"); m_gpu.proj = m_gpu.shader->GetUniformLocation("in_Proj");
m_gpu.normalmat = m_gpu.shader->GetUniformLocation("in_NormalMat"); m_gpu.normalmat = m_gpu.shader->GetUniformLocation("in_NormalMat");
m_gpu.damage = m_gpu.shader->GetUniformLocation("in_Damage"); m_gpu.damage = m_gpu.shader->GetUniformLocation("in_Damage");
m_gpu.lights = m_gpu.shader->GetUniformLocation("u_Lights");
m_gpu.coord = m_gpu.shader->GetAttribLocation("in_Vertex", m_gpu.coord = m_gpu.shader->GetAttribLocation("in_Vertex",
VertexUsage::Position, 0); VertexUsage::Position, 0);
m_gpu.norm = m_gpu.shader->GetAttribLocation("in_Normal", m_gpu.norm = m_gpu.shader->GetAttribLocation("in_Normal",
@@ -125,6 +126,17 @@ void EasyMesh::Render(mat4 const &model, float damage)
mat3 normalmat = transpose(inverse(mat3(modelview))); mat3 normalmat = transpose(inverse(mat3(modelview)));


m_gpu.shader->Bind(); m_gpu.shader->Bind();

/* FIXME: this should be hidden in the shader */
/* FIXME: the 4th component of the position can be used for other things */
Array<Light *> const lights = Scene::GetDefault()->GetLights();
Array<vec4> light_data;
for (int i = 0; i < lights.Count(); ++i)
light_data << lights[i]->GetPosition() << lights[i]->GetColor();
while (light_data.Count() < 8)
light_data << vec4(0.f) << vec4(0.f);
m_gpu.shader->SetUniform(m_gpu.lights, light_data);

m_gpu.shader->SetUniform(m_gpu.modelview, modelview); m_gpu.shader->SetUniform(m_gpu.modelview, modelview);
m_gpu.shader->SetUniform(m_gpu.view, Scene::GetDefault()->GetViewMatrix()); m_gpu.shader->SetUniform(m_gpu.view, Scene::GetDefault()->GetViewMatrix());
m_gpu.shader->SetUniform(m_gpu.invview, inverse(Scene::GetDefault()->GetViewMatrix())); m_gpu.shader->SetUniform(m_gpu.invview, inverse(Scene::GetDefault()->GetViewMatrix()));


+ 1
- 1
src/easymesh/easymesh.h View File

@@ -119,7 +119,7 @@ private:
{ {
Shader *shader; Shader *shader;
ShaderAttrib coord, norm, color; ShaderAttrib coord, norm, color;
ShaderUniform modelview, view, invview, proj, normalmat, damage;
ShaderUniform modelview, view, invview, proj, normalmat, damage, lights;
VertexDeclaration *vdecl; VertexDeclaration *vdecl;
VertexBuffer *vbo; VertexBuffer *vbo;
IndexBuffer *ibo; IndexBuffer *ibo;


+ 39
- 48
src/easymesh/shiny.lolfx View File

@@ -38,24 +38,19 @@ uniform float in_Damage;
uniform mat4 in_View; uniform mat4 in_View;
uniform mat4 in_Inv_View; uniform mat4 in_Inv_View;


uniform vec4 u_Lights[8 * 2];

varying vec4 pass_Vertex; /* View space */ varying vec4 pass_Vertex; /* View space */
varying vec3 pass_TNormal; varying vec3 pass_TNormal;
varying vec4 pass_Color; varying vec4 pass_Color;


// FIXME: all the light parameters should be passed in the code
//Dir Light
vec3 in_LightDir = vec3(-0.3, -0.3, -0.7);

//Point Light
vec4 in_Light2_Pos = vec4(20.0, 10.0, 0.0, 1.0);
float in_Light2_Radius = 20.0;
vec3 in_Light2_diffuse = vec3(0.4, 0.4, 1.0);

#if 0
//Cube Light //Cube Light
vec4 in_Light3_Pos = vec4(-10.0, 10.0, 5.0, 1.0); vec4 in_Light3_Pos = vec4(-10.0, 10.0, 5.0, 1.0);
vec3 in_Light3_Size_Inner = vec3(3.0, 1.0, 3.0); vec3 in_Light3_Size_Inner = vec3(3.0, 1.0, 3.0);
vec3 in_Light3_Size_Outer = vec3(15.0, 15.0, 15.0); vec3 in_Light3_Size_Outer = vec3(15.0, 15.0, 15.0);
vec3 in_Light3_diffuse = vec3(0.4, 1.0, 0.4); vec3 in_Light3_diffuse = vec3(0.4, 1.0, 0.4);
#endif


void main(void) void main(void)
{ {
@@ -64,53 +59,49 @@ void main(void)
float specular_power = 60.0; float specular_power = 60.0;


/* World properties */ /* World properties */
float ambient_mul = 0.5;
vec3 ambient_color = vec3(0.0, 0.0, 0.0);
vec3 diffuse_color = vec3(0.4, 0.4, 0.4);
vec3 specular_color = vec3(1.0, 1.0, 0.6);

vec3 ambient = ambient_color;
vec3 ambient = vec3(0.1, 0.1, 0.1);
vec3 specular = vec3(0.0, 0.0, 0.0); vec3 specular = vec3(0.0, 0.0, 0.0);
vec3 diffuse = vec3(0.0, 0.0, 0.0); vec3 diffuse = vec3(0.0, 0.0, 0.0);
vec3 s = vec3(0.0, 0.0, 0.0);
vec3 v = vec3(0.0, 0.0, 0.0);
vec3 r = vec3(0.0, 0.0, 0.0);
float sdotn = 0.0;
float light_radius_mod = 0.0;

//Light calculation for directional light
s = normalize(-in_LightDir);
v = normalize(-pass_Vertex.xyz);
r = reflect(s, pass_TNormal);

sdotn = max(dot(s, pass_TNormal), 0.0);
diffuse += diffuse_color * sdotn;
if (sdotn > 0.0)
specular += specular_color * specular_reflect
* pow(max(dot(r, v), 0.0), specular_power);
//----------


//Light calculation for point light
vec3 tmpLightDir = (in_View * in_Light2_Pos).xyz - pass_Vertex.xyz;
light_radius_mod = max(0.0, 1.0 - (length(tmpLightDir) / in_Light2_Radius));
s = normalize(tmpLightDir);
v = normalize(-pass_Vertex.xyz);
r = reflect(-s, pass_TNormal);

sdotn = max(dot(s, pass_TNormal), 0.0);
diffuse += in_Light2_diffuse * min(sdotn, light_radius_mod);
if (sdotn > 0.0 && light_radius_mod > 0.0)
specular += specular_color * min(specular_reflect, light_radius_mod)
* pow(max(dot(r, v), 0.0), specular_power);
//----------
/* Light precalculations */
vec3 v = normalize(-pass_Vertex.xyz);

/* Apply lighting */
for (int i = 0; i < 8; i++)
{
vec4 pos = u_Lights[i * 2];
vec4 color = u_Lights[i * 2 + 1];
vec3 s, r;

if (pos.w > 0.0)
{
/* Point light -- no attenuation yet */
s = normalize((in_View * pos).xyz - pass_Vertex.xyz);
r = reflect(-s, pass_TNormal);
}
else
{
/* Directional light */
s = normalize(-pos.xyz);
r = reflect(s, pass_TNormal);
}

float sdotn = max(dot(s, pass_TNormal), 0.0);
diffuse += color.xyz * sdotn;
if (sdotn > 0.0)
specular += color.xyz * specular_reflect
* pow(max(dot(r, v), 0.0), specular_power);
}


#if 0
//Light calculation for cube light //Light calculation for cube light
vec3 specular_color = vec3(1.0, 1.0, 0.6);
vec3 Local_Vertex = (in_Inv_View * pass_Vertex).xyz - (in_Light3_Pos).xyz; vec3 Local_Vertex = (in_Inv_View * pass_Vertex).xyz - (in_Light3_Pos).xyz;
vec3 Proj_Vertex = clamp(Local_Vertex.xyz, -in_Light3_Size_Inner, in_Light3_Size_Inner); vec3 Proj_Vertex = clamp(Local_Vertex.xyz, -in_Light3_Size_Inner, in_Light3_Size_Inner);
vec3 new_LightDir = Local_Vertex - Proj_Vertex; vec3 new_LightDir = Local_Vertex - Proj_Vertex;


vec3 light_radius = max(vec3(0.0,0.0,0.0), vec3(1.0,1.0,1.0) - abs(new_LightDir / in_Light3_Size_Outer)); vec3 light_radius = max(vec3(0.0,0.0,0.0), vec3(1.0,1.0,1.0) - abs(new_LightDir / in_Light3_Size_Outer));
light_radius_mod = min(light_radius.x, min(light_radius.y, light_radius.z));
float light_radius_mod = min(light_radius.x, min(light_radius.y, light_radius.z));


if (length(new_LightDir) == 0.0) if (length(new_LightDir) == 0.0)
sdotn = 1.0; sdotn = 1.0;
@@ -125,11 +116,11 @@ void main(void)
} }
diffuse += in_Light3_diffuse * min(sdotn, light_radius_mod); diffuse += in_Light3_diffuse * min(sdotn, light_radius_mod);
//---------- //----------
#endif


vec3 light = ambient + diffuse + specular; vec3 light = ambient + diffuse + specular;


vec4 real_color = in_Damage * vec4(1.2, 1.2, 1.2, 1.0)
+ (1.0 - in_Damage) * pass_Color;
vec4 real_color = mix(pass_Color, vec4(1.2, 1.2, 1.2, 1.0), in_Damage);
gl_FragColor = real_color * vec4(light, 1.0); gl_FragColor = real_color * vec4(light, 1.0);
} }




+ 1
- 0
src/entity.h View File

@@ -59,6 +59,7 @@ protected:
enum enum
{ {
DRAWGROUP_BEFORE = GAMEGROUP_END, DRAWGROUP_BEFORE = GAMEGROUP_END,
DRAWGROUP_LIGHT,
DRAWGROUP_CAMERA, DRAWGROUP_CAMERA,
DRAWGROUP_DEFAULT, DRAWGROUP_DEFAULT,
DRAWGROUP_HUD, DRAWGROUP_HUD,


+ 71
- 0
src/light.cpp View File

@@ -0,0 +1,71 @@
//
// Lol Engine
//
// Copyright: (c) 2010-2013 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://www.wtfpl.net/ for more details.
//

#if defined HAVE_CONFIG_H
# include "config.h"
#endif

#include <cstring>
#include <cstdlib>

#include "core.h"

namespace lol
{

Light::Light()
: m_color(1.f),
m_directional(true)
{
m_gamegroup = GAMEGROUP_BEFORE;
m_drawgroup = DRAWGROUP_CAMERA;

SetPosition(vec4(0.f));
}

Light::~Light()
{
}

void Light::SetPosition(vec4 const &pos)
{
m_directional = (pos.w > 0.f);
m_position = pos.xyz;
}

vec4 Light::GetPosition()
{
return vec4(m_position, m_directional ? 1.f : 0.f);
}

void Light::SetColor(vec4 const &color)
{
m_color = color;
}

vec4 Light::GetColor()
{
return m_color;
}

void Light::TickGame(float seconds)
{
WorldEntity::TickGame(seconds);
}

void Light::TickDraw(float seconds)
{
WorldEntity::TickDraw(seconds);

Scene::GetDefault()->AddLight(this);
}

} /* namespace lol */


+ 50
- 0
src/light.h View File

@@ -0,0 +1,50 @@
//
// Lol Engine
//
// Copyright: (c) 2010-2013 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://www.wtfpl.net/ for more details.
//

//
// The Light class
// ---------------
//

#if !defined __LIGHT_H__
#define __LIGHT_H__

#include "worldentity.h"

namespace lol
{

class Light : public WorldEntity
{
public:
Light();
~Light();

char const *GetName() { return "<light>"; }

void SetColor(vec4 const &col);
vec4 GetColor();

void SetPosition(vec4 const &pos);
vec4 GetPosition();

protected:
virtual void TickGame(float seconds);
virtual void TickDraw(float seconds);

private:
vec4 m_color;
bool m_directional;
};

} /* namespace lol */

#endif /* __LIGHT_H__ */


+ 2
- 0
src/lolcore.vcxproj View File

@@ -273,6 +273,7 @@
<ClCompile Include="input\keyboard.cpp" /> <ClCompile Include="input\keyboard.cpp" />
<ClCompile Include="input\stick.cpp" /> <ClCompile Include="input\stick.cpp" />
<ClCompile Include="layer.cpp" /> <ClCompile Include="layer.cpp" />
<ClCompile Include="light.cpp" />
<ClCompile Include="map.cpp" /> <ClCompile Include="map.cpp" />
<ClCompile Include="math\geometry.cpp" /> <ClCompile Include="math\geometry.cpp" />
<ClCompile Include="math\half.cpp" /> <ClCompile Include="math\half.cpp" />
@@ -583,6 +584,7 @@
<ClInclude Include="input\keyboard.h" /> <ClInclude Include="input\keyboard.h" />
<ClInclude Include="input\stick.h" /> <ClInclude Include="input\stick.h" />
<ClInclude Include="layer.h" /> <ClInclude Include="layer.h" />
<ClInclude Include="light.h" />
<ClInclude Include="loldebug.h" /> <ClInclude Include="loldebug.h" />
<ClInclude Include="lolgl.h" /> <ClInclude Include="lolgl.h" />
<ClInclude Include="lol\base\array.h" /> <ClInclude Include="lol\base\array.h" />


+ 6
- 0
src/lolcore.vcxproj.filters View File

@@ -189,6 +189,9 @@
<ClCompile Include="layer.cpp"> <ClCompile Include="layer.cpp">
<Filter>...</Filter> <Filter>...</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="light.cpp">
<Filter>...</Filter>
</ClCompile>
<ClCompile Include="ticker.cpp"> <ClCompile Include="ticker.cpp">
<Filter>...</Filter> <Filter>...</Filter>
</ClCompile> </ClCompile>
@@ -776,6 +779,9 @@
<ClInclude Include="layer.h"> <ClInclude Include="layer.h">
<Filter>...</Filter> <Filter>...</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="light.h">
<Filter>...</Filter>
</ClInclude>
<ClInclude Include="loldebug.h"> <ClInclude Include="loldebug.h">
<Filter>...</Filter> <Filter>...</Filter>
</ClInclude> </ClInclude>


+ 30
- 18
src/scene.cpp View File

@@ -61,7 +61,8 @@ private:
mat4 m_view_matrix; mat4 m_view_matrix;
mat4 m_proj_matrix; mat4 m_proj_matrix;


Array<Tile> tiles;
Array<Tile> m_tiles;
Array<Light *> m_lights;


Shader *m_shader; Shader *m_shader;
VertexDeclaration *m_vdecl; VertexDeclaration *m_vdecl;
@@ -113,6 +114,7 @@ void Scene::Reset()
for (int i = 0; i < data->bufs.Count(); i++) for (int i = 0; i < data->bufs.Count(); i++)
delete data->bufs[i]; delete data->bufs[i];
data->bufs.Empty(); data->bufs.Empty();
data->m_lights.Empty();
} }


void Scene::SetViewMatrix(mat4 const &m) void Scene::SetViewMatrix(mat4 const &m)
@@ -146,13 +148,23 @@ void Scene::AddTile(TileSet *tileset, int id, vec3 pos, int o, vec2 scale)
t.o = o; t.o = o;
t.scale = scale; t.scale = scale;


data->tiles.Push(t);
data->m_tiles.Push(t);
}

void Scene::AddLight(Light *l)
{
data->m_lights.Push(l);
}

Array<Light *> const &Scene::GetLights() const
{
return data->m_lights;
} }


void Scene::Render() // XXX: rename to Blit() void Scene::Render() // XXX: rename to Blit()
{ {
/* Early exit if nothing needs to be rendered */ /* Early exit if nothing needs to be rendered */
if (!data->tiles.Count())
if (!data->m_tiles.Count())
return; return;


if (!data->m_shader) if (!data->m_shader)
@@ -160,15 +172,15 @@ void Scene::Render() // XXX: rename to Blit()


#if 0 #if 0
// Randomise, then sort. // Randomise, then sort.
for (int i = 0; i < data->tiles.Count(); i++)
for (int i = 0; i < data->m_tiles.Count(); i++)
{ {
Tile tmp = data->tiles[i];
int j = rand() % data->tiles.Count();
data->tiles[i] = data->tiles[j];
data->tiles[j] = tmp;
Tile tmp = data->m_tiles[i];
int j = rand() % data->m_tiles.Count();
data->m_tiles[i] = data->m_tiles[j];
data->m_tiles[j] = tmp;
} }
#endif #endif
qsort(&data->tiles[0], data->tiles.Count(),
qsort(&data->m_tiles[0], data->m_tiles.Count(),
sizeof(Tile), SceneData::Compare); sizeof(Tile), SceneData::Compare);


// XXX: debug stuff // XXX: debug stuff
@@ -219,11 +231,11 @@ void Scene::Render() // XXX: rename to Blit()
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#endif #endif


for (int buf = 0, i = 0, n; i < data->tiles.Count(); i = n, buf += 2)
for (int buf = 0, i = 0, n; i < data->m_tiles.Count(); i = n, buf += 2)
{ {
/* Count how many quads will be needed */ /* Count how many quads will be needed */
for (n = i + 1; n < data->tiles.Count(); n++)
if (data->tiles[i].tileset != data->tiles[n].tileset)
for (n = i + 1; n < data->m_tiles.Count(); n++)
if (data->m_tiles[i].tileset != data->m_tiles[n].tileset)
break; break;


/* Create a vertex array object */ /* Create a vertex array object */
@@ -237,9 +249,9 @@ void Scene::Render() // XXX: rename to Blit()


for (int j = i; j < n; j++) for (int j = i; j < n; j++)
{ {
data->tiles[i].tileset->BlitTile(data->tiles[j].id,
data->tiles[j].pos, data->tiles[j].o,
data->tiles[j].scale,
data->m_tiles[i].tileset->BlitTile(data->m_tiles[j].id,
data->m_tiles[j].pos, data->m_tiles[j].o,
data->m_tiles[j].scale,
vertex + 18 * (j - i), texture + 12 * (j - i)); vertex + 18 * (j - i), texture + 12 * (j - i));
} }


@@ -247,7 +259,7 @@ void Scene::Render() // XXX: rename to Blit()
vb2->Unlock(); vb2->Unlock();


/* Bind texture */ /* Bind texture */
data->tiles[i].tileset->Bind();
data->m_tiles[i].tileset->Bind();


/* Bind vertex and texture coordinate buffers */ /* Bind vertex and texture coordinate buffers */
data->m_vdecl->Bind(); data->m_vdecl->Bind();
@@ -257,10 +269,10 @@ void Scene::Render() // XXX: rename to Blit()
/* Draw arrays */ /* Draw arrays */
data->m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, (n - i) * 6); data->m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, (n - i) * 6);
data->m_vdecl->Unbind(); data->m_vdecl->Unbind();
data->tiles[i].tileset->Unbind();
data->m_tiles[i].tileset->Unbind();
} }


data->tiles.Empty();
data->m_tiles.Empty();


data->m_shader->Unbind(); data->m_shader->Unbind();




+ 4
- 0
src/scene.h View File

@@ -19,6 +19,7 @@
#include <stdint.h> #include <stdint.h>


#include "tileset.h" #include "tileset.h"
#include "light.h"


namespace lol namespace lol
{ {
@@ -45,6 +46,9 @@ public:
* the architecture we want to build */ * the architecture we want to build */
void AddTile(TileSet *tileset, int id, vec3 pos, int o, vec2 scale); void AddTile(TileSet *tileset, int id, vec3 pos, int o, vec2 scale);


void AddLight(Light *light);
Array<Light *> const &GetLights() const;

private: private:
SceneData *data; SceneData *data;
}; };


+ 15
- 0
tutorial/05_easymesh.cpp View File

@@ -54,12 +54,26 @@ public:
m_camera->SetPosition(vec3(-15.f, 5.f, 0.f)); m_camera->SetPosition(vec3(-15.f, 5.f, 0.f));
Ticker::Ref(m_camera); Ticker::Ref(m_camera);


/* Add a white directional light */
m_light1 = new Light();
m_light1->SetPosition(vec4(0.2f, 0.2f, 0.f, 0.f));
m_light1->SetColor(vec4(0.5f, 0.5f, 0.5f, 1.f));
Ticker::Ref(m_light1);

/* Add an orangeish point light */
m_light2 = new Light();
m_light2->SetPosition(vec4(-15.f, 15.f, 15.f, 1.f));
m_light2->SetColor(vec4(0.4f, 0.3f, 0.2f, 1.f));
Ticker::Ref(m_light2);

m_ready = false; m_ready = false;
} }


~EasyMeshTutorial() ~EasyMeshTutorial()
{ {
Ticker::Unref(m_camera); Ticker::Unref(m_camera);
Ticker::Unref(m_light1);
Ticker::Unref(m_light2);
} }


virtual void TickGame(float seconds) virtual void TickGame(float seconds)
@@ -114,6 +128,7 @@ private:
float m_angle; float m_angle;
mat4 m_mat; mat4 m_mat;
Camera *m_camera; Camera *m_camera;
Light *m_light1, *m_light2;


bool m_ready; bool m_ready;
}; };


Loading…
Cancel
Save