Sfoglia il codice sorgente

easymesh: interface the shiny shader with new Light objects.

legacy
Sam Hocevar sam 12 anni fa
parent
commit
0ba4e6d9e0
13 ha cambiato i file con 233 aggiunte e 67 eliminazioni
  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 Vedi File

@@ -14,6 +14,7 @@ liblol_a_SOURCES = \
profiler.cpp profiler.h text.cpp text.h emitter.cpp emitter.h numeric.h \
worldentity.cpp worldentity.h gradient.cpp gradient.h gradient.lolfx \
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/string.h lol/base/hash.h lol/base/map.h \


+ 1
- 0
src/core.h Vedi File

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

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


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

@@ -79,6 +79,7 @@ void EasyMesh::MeshConvert(Shader* provided_shader)
m_gpu.proj = m_gpu.shader->GetUniformLocation("in_Proj");
m_gpu.normalmat = m_gpu.shader->GetUniformLocation("in_NormalMat");
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",
VertexUsage::Position, 0);
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)));

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.view, Scene::GetDefault()->GetViewMatrix());
m_gpu.shader->SetUniform(m_gpu.invview, inverse(Scene::GetDefault()->GetViewMatrix()));


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

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


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

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

uniform vec4 u_Lights[8 * 2];

varying vec4 pass_Vertex; /* View space */
varying vec3 pass_TNormal;
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
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_Outer = vec3(15.0, 15.0, 15.0);
vec3 in_Light3_diffuse = vec3(0.4, 1.0, 0.4);
#endif

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

/* 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 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
vec3 specular_color = vec3(1.0, 1.0, 0.6);
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 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));
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)
sdotn = 1.0;
@@ -125,11 +116,11 @@ void main(void)
}
diffuse += in_Light3_diffuse * min(sdotn, light_radius_mod);
//----------
#endif

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);
}



+ 1
- 0
src/entity.h Vedi File

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


+ 71
- 0
src/light.cpp Vedi 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 Vedi 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 Vedi File

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


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

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


+ 30
- 18
src/scene.cpp Vedi File

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

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

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

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.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()
{
/* Early exit if nothing needs to be rendered */
if (!data->tiles.Count())
if (!data->m_tiles.Count())
return;

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

#if 0
// 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
qsort(&data->tiles[0], data->tiles.Count(),
qsort(&data->m_tiles[0], data->m_tiles.Count(),
sizeof(Tile), SceneData::Compare);

// XXX: debug stuff
@@ -219,11 +231,11 @@ void Scene::Render() // XXX: rename to Blit()
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#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 */
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;

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

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));
}

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

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

/* Bind vertex and texture coordinate buffers */
data->m_vdecl->Bind();
@@ -257,10 +269,10 @@ void Scene::Render() // XXX: rename to Blit()
/* Draw arrays */
data->m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, (n - i) * 6);
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();



+ 4
- 0
src/scene.h Vedi File

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

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

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

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

private:
SceneData *data;
};


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

@@ -54,12 +54,26 @@ public:
m_camera->SetPosition(vec3(-15.f, 5.f, 0.f));
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;
}

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

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

bool m_ready;
};


||||||
x
 
000:0
Caricamento…
Annulla
Salva