wip
This commit is contained in:
352
wip/CShader.cpp
Executable file
352
wip/CShader.cpp
Executable file
@@ -0,0 +1,352 @@
|
|||||||
|
/**************************************************************
|
||||||
|
file: CShader.h
|
||||||
|
author: Stephan Gödecker (Masterhawk studios)
|
||||||
|
version: rev. 5
|
||||||
|
|
||||||
|
description: this file was created to achieve a dynamic
|
||||||
|
management for GLSL shaders with irrlicht. After implementing
|
||||||
|
this code-snippet the user is able to dynamically load GLSL-
|
||||||
|
shader in his irrlicht application. The shader just have to
|
||||||
|
be additionally defined by a special xml-file. You can get
|
||||||
|
further information at:
|
||||||
|
|
||||||
|
http://www.masterhawk.dyndns.org/wordpress?p=267
|
||||||
|
|
||||||
|
***************************************************************/
|
||||||
|
|
||||||
|
#include "CShader.h"
|
||||||
|
|
||||||
|
rc_shader_value_obj rc_shader_float(float n)
|
||||||
|
{
|
||||||
|
rc_shader_value_obj v;
|
||||||
|
v.type = RC_SHADER_VALUE_TYPE_FLOAT;
|
||||||
|
v.fvalue = n;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_shader_value_obj rc_shader_string(std::string s)
|
||||||
|
{
|
||||||
|
rc_shader_value_obj v;
|
||||||
|
v.type = RC_SHADER_VALUE_TYPE_STRING;
|
||||||
|
v.svalue = s;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
CShader::CShader(IrrlichtDevice* device, rc_shader_material_obj shader_material)
|
||||||
|
{
|
||||||
|
|
||||||
|
dev=device;
|
||||||
|
|
||||||
|
f_old_cycle_time = dev->getTimer()->getRealTime();
|
||||||
|
|
||||||
|
driver = device->getVideoDriver();
|
||||||
|
|
||||||
|
//Missing xml-handling
|
||||||
|
|
||||||
|
video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices();
|
||||||
|
p_material = 0;
|
||||||
|
|
||||||
|
if(gpu)
|
||||||
|
{
|
||||||
|
p_material = gpu->addHighLevelShaderMaterial(
|
||||||
|
shader_material.vert_shader.c_str(), "vertexMain", video::EVST_VS_4_1,
|
||||||
|
shader_material.frag_shader.c_str(), "pixelMain", video::EPST_PS_4_1,
|
||||||
|
this, video::EMT_SOLID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for(s32 i=0; i<shader_material.shader_object.size(); i++)
|
||||||
|
{
|
||||||
|
//create new uniform variable
|
||||||
|
SShaderVariable* shader_var = new SShaderVariable();
|
||||||
|
shader_var->predefinition = ESPV_NONE;
|
||||||
|
|
||||||
|
irr::core::stringc type( shader_material.shader_object[i].type.c_str() );
|
||||||
|
|
||||||
|
if(type.equals_ignore_case("float"))
|
||||||
|
shader_var->type = ESVT_FLOAT;
|
||||||
|
else if(type.equals_ignore_case("vec2"))
|
||||||
|
shader_var->type = ESVT_VEC2;
|
||||||
|
else if(type.equals_ignore_case("vec3"))
|
||||||
|
shader_var->type = ESVT_VEC3;
|
||||||
|
else if(type.equals_ignore_case("vec4"))
|
||||||
|
shader_var->type = ESVT_VEC4;
|
||||||
|
else if(type.equals_ignore_case("mat4"))
|
||||||
|
shader_var->type = ESVT_MAT4;
|
||||||
|
else if(type.equals_ignore_case("sampler2d"))
|
||||||
|
shader_var->type = ESVT_SAMPLER2D;
|
||||||
|
else if(type.equals_ignore_case("predefined"))
|
||||||
|
shader_var->type = ESVT_PREDEFINED;
|
||||||
|
|
||||||
|
shader_var->name = core::stringc( shader_material.shader_object[i].name.c_str() );
|
||||||
|
|
||||||
|
|
||||||
|
shader_var->b_frag_var = shader_material.shader_object[i].fragVar;
|
||||||
|
|
||||||
|
switch(shader_var->type)
|
||||||
|
{
|
||||||
|
case ESVT_SAMPLER2D:
|
||||||
|
case ESVT_FLOAT:
|
||||||
|
{
|
||||||
|
float* vars = new float[1];
|
||||||
|
vars[0] = shader_material.shader_object[i].value[0].fvalue;
|
||||||
|
shader_var->value = vars;
|
||||||
|
|
||||||
|
}break;
|
||||||
|
|
||||||
|
/*case ESVT_SAMPLER2D:
|
||||||
|
{
|
||||||
|
int tex = 0;
|
||||||
|
|
||||||
|
TiXmlNode* value = node->FirstChild("value");
|
||||||
|
|
||||||
|
tex = ((TiXmlElement*)value)->FirstAttribute()->IntValue();
|
||||||
|
|
||||||
|
float* vars = new float[1];
|
||||||
|
vars = (float*)(&tex);
|
||||||
|
shader_var->value = vars;
|
||||||
|
}break;*/
|
||||||
|
|
||||||
|
case ESVT_VEC2:
|
||||||
|
{
|
||||||
|
float* vars = new float[2];
|
||||||
|
|
||||||
|
for(s32 j=0; j<2; j++)
|
||||||
|
{
|
||||||
|
vars[j] = shader_material.shader_object[i].value[j].fvalue;
|
||||||
|
}
|
||||||
|
shader_var->value = vars;
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case ESVT_VEC3:
|
||||||
|
{
|
||||||
|
float* vars = new float[3];
|
||||||
|
|
||||||
|
for(s32 j=0; j<3; j++)
|
||||||
|
{
|
||||||
|
vars[j] = shader_material.shader_object[i].value[j].fvalue;
|
||||||
|
}
|
||||||
|
shader_var->value = vars;
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case ESVT_VEC4:
|
||||||
|
{
|
||||||
|
float* vars = new float[4];
|
||||||
|
|
||||||
|
for(s32 j=0; j<4; j++)
|
||||||
|
{
|
||||||
|
vars[j] = shader_material.shader_object[i].value[j].fvalue;
|
||||||
|
}
|
||||||
|
shader_var->value = vars;
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case ESVT_MAT4:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESVT_PREDEFINED:
|
||||||
|
{
|
||||||
|
core::stringc str_val(shader_material.shader_object[i].value[0].svalue.c_str());
|
||||||
|
|
||||||
|
shader_var->value = 0;
|
||||||
|
|
||||||
|
if(str_val.equals_ignore_case("predefined_eye_position"))
|
||||||
|
shader_var->predefinition = ESPV_EYEPOSITION;
|
||||||
|
else if(str_val.equals_ignore_case("predefined_mat4_view_proj"))
|
||||||
|
{
|
||||||
|
shader_var->predefinition = ESPV_MAT4_VIEW_PROJ;
|
||||||
|
}
|
||||||
|
else if(str_val.equals_ignore_case("predefined_mat4_view"))
|
||||||
|
{
|
||||||
|
shader_var->predefinition = ESPV_MAT4_VIEW;
|
||||||
|
}
|
||||||
|
else if(str_val.equals_ignore_case("predefined_float_time0x"))
|
||||||
|
{
|
||||||
|
shader_var->predefinition = ESPV_FLOAT_TIME0X;
|
||||||
|
shader_var->value = new float[1];
|
||||||
|
shader_var->value[0] = 0.f;
|
||||||
|
}
|
||||||
|
else if(str_val.equals_ignore_case("predefined_rtt_view"))
|
||||||
|
{
|
||||||
|
shader_var->predefinition = ESPV_NONE;
|
||||||
|
shader_var->type = ESVT_SAMPLER2D;
|
||||||
|
|
||||||
|
float* vars = new float[1];
|
||||||
|
|
||||||
|
vars[0] = (shader_material.shader_object[i].additional_value.size() > 0 ? shader_material.shader_object[i].additional_value[0].fvalue : 0);
|
||||||
|
|
||||||
|
shader_var->value = vars;
|
||||||
|
|
||||||
|
//registering for RTT_VIEW
|
||||||
|
S_RTT_Info* rtt_info = new S_RTT_Info();
|
||||||
|
rtt_info->type = ERT_VIEW;
|
||||||
|
rtt_info->tex_channel = (int)vars[0];
|
||||||
|
rtt_infos.push_back(rtt_info);
|
||||||
|
|
||||||
|
rtt_info = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("ERROR: Unknown predefinition: %s\n",str_val.c_str());
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
/// printf("(XML PARSER) ERROR: No type for uniform shader variable specified: %s\n",shader_var->name);
|
||||||
|
break;
|
||||||
|
}//end switch
|
||||||
|
|
||||||
|
uniform_variables.push_back(shader_var);
|
||||||
|
}
|
||||||
|
//printf("(MATERIAL PARSER) Initialized %i uniform variables\n",uniform_variables.size());
|
||||||
|
for(s32 i=0; i<uniform_variables.size(); i++)
|
||||||
|
{
|
||||||
|
//printf("(MATERIAL PARSER) VAR%i: %s VALUE: ",i,uniform_variables[i]->name.c_str());
|
||||||
|
if(uniform_variables[i]->type == ESVT_PREDEFINED)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
s32 element_count = (uniform_variables[i]->type != ESVT_SAMPLER2D) ? (s32)uniform_variables[i]->type : 1;
|
||||||
|
//for(s32 j=0; j<element_count; j++)
|
||||||
|
//if(uniform_variables[i]->type != ESVT_SAMPLER2D)
|
||||||
|
//printf("%f ",(uniform_variables[i]->value[j]));
|
||||||
|
//else
|
||||||
|
//printf("%i",*uniform_variables[i]->value);
|
||||||
|
//printf("\n\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CShader::OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
|
||||||
|
{
|
||||||
|
for(s32 i=0; i<uniform_variables.size(); i++)
|
||||||
|
{
|
||||||
|
int element_count = 0;
|
||||||
|
switch(uniform_variables[i]->type)
|
||||||
|
{
|
||||||
|
case ESVT_SAMPLER2D:
|
||||||
|
element_count = 1;
|
||||||
|
break;
|
||||||
|
case ESVT_PREDEFINED:
|
||||||
|
{
|
||||||
|
switch(uniform_variables[i]->predefinition)
|
||||||
|
{
|
||||||
|
case ESPV_EYEPOSITION:
|
||||||
|
{
|
||||||
|
if(uniform_variables[i]->value)
|
||||||
|
{
|
||||||
|
delete[] uniform_variables[i]->value;
|
||||||
|
uniform_variables[i]->value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uniform_variables[i]->value = new float[3];
|
||||||
|
core::vector3df cam_pos = dev->getSceneManager()->getActiveCamera()->getAbsolutePosition();
|
||||||
|
uniform_variables[i]->value[0] = cam_pos.X;
|
||||||
|
uniform_variables[i]->value[1] = cam_pos.Y;
|
||||||
|
uniform_variables[i]->value[2] = cam_pos.Z;
|
||||||
|
|
||||||
|
element_count = 3;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESPV_MAT4_VIEW:
|
||||||
|
{
|
||||||
|
core::matrix4 mat_view = dev->getVideoDriver()->getTransform(video::ETS_VIEW);
|
||||||
|
|
||||||
|
uniform_variables[i]->value = mat_view.pointer();
|
||||||
|
|
||||||
|
element_count = 16;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESPV_MAT4_VIEW_PROJ:
|
||||||
|
{
|
||||||
|
core::matrix4 mat_view_proj = dev->getVideoDriver()->getTransform(video::ETS_PROJECTION);
|
||||||
|
|
||||||
|
mat_view_proj *= dev->getVideoDriver()->getTransform(video::ETS_VIEW);
|
||||||
|
|
||||||
|
uniform_variables[i]->value = mat_view_proj.pointer();
|
||||||
|
|
||||||
|
element_count = 16;
|
||||||
|
|
||||||
|
/*printf("VIEW_PROJECTION_MATRIX\n");
|
||||||
|
for(int k=0; k<16; k++)
|
||||||
|
{
|
||||||
|
printf("%f ",uniform_variables[i]->value[k]);
|
||||||
|
if(k==3 || k==7 || k==11 || k==15) printf("\n");
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESPV_FLOAT_TIME0X:
|
||||||
|
{
|
||||||
|
|
||||||
|
f32 f_time_diff = dev->getTimer()->getRealTime() - f_old_cycle_time;
|
||||||
|
|
||||||
|
uniform_variables[i]->value[0] += f_time_diff / 1000;
|
||||||
|
|
||||||
|
s32 i_tmp = uniform_variables[i]->value[0] / 120;
|
||||||
|
|
||||||
|
uniform_variables[i]->value[0] = uniform_variables[i]->value[0] - (i_tmp*120);
|
||||||
|
|
||||||
|
f_old_cycle_time = dev->getTimer()->getRealTime();
|
||||||
|
|
||||||
|
element_count = 1;
|
||||||
|
|
||||||
|
//printf("FLOAT_TIME0X = %f\n",uniform_variables[i]->value[0]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
element_count = (s32)uniform_variables[i]->type;
|
||||||
|
}
|
||||||
|
if(uniform_variables[i]->b_frag_var)
|
||||||
|
if(uniform_variables[i]->type != ESVT_SAMPLER2D)
|
||||||
|
services->setPixelShaderConstant(uniform_variables[i]->name.c_str(),uniform_variables[i]->value,element_count);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int tex = *uniform_variables[i]->value;
|
||||||
|
services->setPixelShaderConstant(uniform_variables[i]->name.c_str(),(float*)(&tex),element_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
if(uniform_variables[i]->type != ESVT_SAMPLER2D)
|
||||||
|
services->setVertexShaderConstant(uniform_variables[i]->name.c_str(),uniform_variables[i]->value,element_count);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int tex = *uniform_variables[i]->value;
|
||||||
|
services->setVertexShaderConstant(uniform_variables[i]->name.c_str(),(int*)(&tex),element_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 CShader::getMaterial()
|
||||||
|
{
|
||||||
|
return p_material;
|
||||||
|
}
|
||||||
|
|
||||||
|
S_RTT_Info* CShader::getRTTInfo(E_RTT_TEXTURE rtt)
|
||||||
|
{
|
||||||
|
for(s32 i=0; i<rtt_infos.size(); i++)
|
||||||
|
{
|
||||||
|
if(rtt == rtt_infos[i]->type)
|
||||||
|
return rtt_infos[i];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CShader::~CShader()
|
||||||
|
{
|
||||||
|
for(s32 i=0; i<uniform_variables.size(); i++)
|
||||||
|
{
|
||||||
|
if(uniform_variables[i]->predefinition != ESPV_MAT4_VIEW_PROJ && uniform_variables[i]->predefinition != ESPV_MAT4_VIEW)
|
||||||
|
delete[] uniform_variables[i]->value;
|
||||||
|
|
||||||
|
delete uniform_variables[i];
|
||||||
|
uniform_variables[i] = 0;
|
||||||
|
}
|
||||||
|
uniform_variables.clear();
|
||||||
|
}
|
||||||
117
wip/CShader.h
Executable file
117
wip/CShader.h
Executable file
@@ -0,0 +1,117 @@
|
|||||||
|
/**************************************************************
|
||||||
|
file: CShader.h
|
||||||
|
author: Stephan Gödecker (Masterhawk studios)
|
||||||
|
version: rev. 5
|
||||||
|
|
||||||
|
description: this file was created to achieve a dynamic
|
||||||
|
management for GLSL shaders with irrlicht. After implementing
|
||||||
|
this code-snippet the user is able to dynamically load GLSL-
|
||||||
|
shader in his irrlicht application. The shader just have to
|
||||||
|
be additionally defined by a special xml-file. You can get
|
||||||
|
further information at:
|
||||||
|
|
||||||
|
http://www.masterhawk.dyndns.org/wordpress?p=267
|
||||||
|
|
||||||
|
***************************************************************/
|
||||||
|
|
||||||
|
//#include "stdafx.h"
|
||||||
|
#include <irrlicht.h>
|
||||||
|
#include "XML/tinyxml.h"
|
||||||
|
|
||||||
|
using namespace irr;
|
||||||
|
|
||||||
|
#define RC_SHADER_VALUE_TYPE_FLOAT 0
|
||||||
|
#define RC_SHADER_VALUE_TYPE_STRING 1
|
||||||
|
|
||||||
|
struct rc_shader_value_obj
|
||||||
|
{
|
||||||
|
int type;
|
||||||
|
float fvalue;
|
||||||
|
std::string svalue;
|
||||||
|
};
|
||||||
|
|
||||||
|
rc_shader_value_obj rc_shader_float(float n);
|
||||||
|
rc_shader_value_obj rc_shader_string(std::string s);
|
||||||
|
|
||||||
|
struct rc_shader_obj
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
std::string type;
|
||||||
|
bool fragVar;
|
||||||
|
bool artistVar;
|
||||||
|
irr::core::array<rc_shader_value_obj> value;
|
||||||
|
irr::core::array<rc_shader_value_obj> additional_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rc_shader_material_obj
|
||||||
|
{
|
||||||
|
std::string frag_shader;
|
||||||
|
std::string vert_shader;
|
||||||
|
irr::core::array<rc_shader_obj> shader_object;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum E_SHADER_VAR_TYPE
|
||||||
|
{
|
||||||
|
ESVT_FLOAT = 1,
|
||||||
|
ESVT_VEC2 = 2,
|
||||||
|
ESVT_VEC3 = 3,
|
||||||
|
ESVT_VEC4 = 4,
|
||||||
|
ESVT_MAT4 = 16,
|
||||||
|
ESVT_SAMPLER2D,
|
||||||
|
ESVT_PREDEFINED
|
||||||
|
};
|
||||||
|
enum E_SHADER_PREDEFINED_VARS
|
||||||
|
{
|
||||||
|
ESPV_NONE,
|
||||||
|
ESPV_FLOAT_TIME0X,
|
||||||
|
ESPV_EYEPOSITION,
|
||||||
|
ESPV_MAT4_VIEW,
|
||||||
|
ESPV_MAT4_VIEW_PROJ,
|
||||||
|
ESPV_RTT_VIEW
|
||||||
|
};
|
||||||
|
|
||||||
|
enum E_RTT_TEXTURE
|
||||||
|
{
|
||||||
|
ERT_VIEW = 0x0001
|
||||||
|
};
|
||||||
|
|
||||||
|
struct S_RTT_Info
|
||||||
|
{
|
||||||
|
E_RTT_TEXTURE type;
|
||||||
|
s32 tex_channel;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SShaderVariable
|
||||||
|
{
|
||||||
|
core::stringc name;
|
||||||
|
E_SHADER_VAR_TYPE type;
|
||||||
|
E_SHADER_PREDEFINED_VARS predefinition;
|
||||||
|
bool b_frag_var;
|
||||||
|
float* value;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CShader : public video::IShaderConstantSetCallBack
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
s32 p_material; //material which has to be applied to a scene_node
|
||||||
|
IrrlichtDevice* dev;
|
||||||
|
video::IVideoDriver* driver;
|
||||||
|
|
||||||
|
//temporarily
|
||||||
|
TiXmlDocument doc;
|
||||||
|
core::array<SShaderVariable*> uniform_variables;
|
||||||
|
|
||||||
|
core::array<S_RTT_Info*> rtt_infos;
|
||||||
|
|
||||||
|
f32 f_old_cycle_time;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CShader(IrrlichtDevice* device, rc_shader_material_obj shader_material);
|
||||||
|
~CShader();
|
||||||
|
|
||||||
|
virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData);
|
||||||
|
|
||||||
|
s32 getMaterial();
|
||||||
|
|
||||||
|
S_RTT_Info* getRTTInfo(E_RTT_TEXTURE rtt);
|
||||||
|
};
|
||||||
354
wip/DynamicShaderExample.cpp
Executable file
354
wip/DynamicShaderExample.cpp
Executable file
@@ -0,0 +1,354 @@
|
|||||||
|
/* DynamicShaderExample
|
||||||
|
* Masterhawk studios 2011 - http://masterhawk.dyndns.org/wordpress
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This is a simple example how to use the "Dynamic Shaders for Irrlicht"
|
||||||
|
* by Masterhawk studios in your own application. This example shows how
|
||||||
|
* to use all provided features, especially the glass refraction, since
|
||||||
|
* it needs your application to support RTTs
|
||||||
|
*/
|
||||||
|
|
||||||
|
//////////////////////////////////
|
||||||
|
// DON'T FORGET TO LINK //
|
||||||
|
// //
|
||||||
|
// IRRLICHT.LIB //
|
||||||
|
// IRRLICHT-INCLUDE-DIRECTORY //
|
||||||
|
// TINYXML.LIB //
|
||||||
|
// TINYXML-INCLUDE-DIRECTORY //
|
||||||
|
// //
|
||||||
|
// TO YOUR PROJECT //
|
||||||
|
//////////////////////////////////
|
||||||
|
|
||||||
|
//stdafx inlcudes the irrlicht.h inclusion
|
||||||
|
//#include "stdafx.h"
|
||||||
|
#include <irrlicht.h>
|
||||||
|
//don't forget to include the CShader source
|
||||||
|
#include "CShader.h"
|
||||||
|
|
||||||
|
|
||||||
|
//simple Irrlicht setup stuff
|
||||||
|
using namespace irr;
|
||||||
|
|
||||||
|
IrrlichtDevice* device = 0;
|
||||||
|
video::IVideoDriver* driver = 0;
|
||||||
|
scene::ISceneManager* smgr = 0;
|
||||||
|
scene::ICameraSceneNode* cam = 0;
|
||||||
|
|
||||||
|
std::string refraction1_vert =
|
||||||
|
"varying vec3 Normal; \n"
|
||||||
|
"varying vec3 EyeDir; \n"
|
||||||
|
"varying vec4 EyePos; \n"
|
||||||
|
"varying float LightIntensity; \n"
|
||||||
|
"\n"
|
||||||
|
"void main(void) \n"
|
||||||
|
"{ \n"
|
||||||
|
" gl_Position = ftransform(); \n"
|
||||||
|
" Normal = normalize(gl_NormalMatrix * gl_Normal); \n"
|
||||||
|
" vec4 pos = gl_ModelViewMatrix * gl_Vertex; \n"
|
||||||
|
" EyeDir = pos.xyz; \n"
|
||||||
|
" EyePos = gl_ModelViewProjectionMatrix * gl_Vertex; \n"
|
||||||
|
" LightIntensity = max(dot(normalize(gl_LightSource[0].position.xyz - EyeDir), Normal), 0.0); \n"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
std::string refraction1_frag =
|
||||||
|
"const vec3 Xunitvec = vec3 (1.0, 0.0, 0.0); \n"
|
||||||
|
"const vec3 Yunitvec = vec3 (0.0, 1.0, 0.0); \n"
|
||||||
|
" \n"
|
||||||
|
"uniform vec3 BaseColor; \n"
|
||||||
|
"uniform float Depth; \n"
|
||||||
|
"uniform float MixRatio; \n"
|
||||||
|
" \n"
|
||||||
|
"// need to scale our framebuffer - it has a fixed width/height of 2048 \n"
|
||||||
|
"uniform float FrameWidth; \n"
|
||||||
|
"uniform float FrameHeight; \n"
|
||||||
|
" \n"
|
||||||
|
"uniform sampler2D EnvMap; \n"
|
||||||
|
"uniform sampler2D RefractionMap; \n"
|
||||||
|
" \n"
|
||||||
|
"varying vec3 Normal; \n"
|
||||||
|
"varying vec3 EyeDir; \n"
|
||||||
|
"varying vec4 EyePos; \n"
|
||||||
|
"varying float LightIntensity; \n"
|
||||||
|
" \n"
|
||||||
|
"void main (void) \n"
|
||||||
|
"{ \n"
|
||||||
|
" // Compute reflection vector \n"
|
||||||
|
" vec3 reflectDir = reflect(EyeDir, Normal); \n"
|
||||||
|
" \n"
|
||||||
|
" // Compute altitude and azimuth angles \n"
|
||||||
|
" \n"
|
||||||
|
" vec2 index; \n"
|
||||||
|
" \n"
|
||||||
|
" index.y = dot(normalize(reflectDir), Yunitvec); \n"
|
||||||
|
" reflectDir.y = 0.0; \n"
|
||||||
|
" index.x = dot(normalize(reflectDir), Xunitvec) * 0.5; \n"
|
||||||
|
" \n"
|
||||||
|
" // Translate index values into proper range \n"
|
||||||
|
" \n"
|
||||||
|
" if (reflectDir.z >= 0.0) \n"
|
||||||
|
" index = (index + 1.0) * 0.5; \n"
|
||||||
|
" else \n"
|
||||||
|
" { \n"
|
||||||
|
" index.t = (index.t + 1.0) * 0.5; \n"
|
||||||
|
" index.s = (-index.s) * 0.5 + 1.0; \n"
|
||||||
|
" } \n"
|
||||||
|
" \n"
|
||||||
|
" // if reflectDir.z >= 0.0, s will go from 0.25 to 0.75 \n"
|
||||||
|
" // if reflectDir.z < 0.0, s will go from 0.75 to 1.25, and \n"
|
||||||
|
" // that's OK, because we've set the texture to wrap. \n"
|
||||||
|
" \n"
|
||||||
|
" // Do a lookup into the environment map. \n"
|
||||||
|
" \n"
|
||||||
|
" vec3 envColor = vec3 (texture2D(EnvMap, index)); \n"
|
||||||
|
" \n"
|
||||||
|
" // calc fresnels term. This allows a view dependant blend of reflection/refraction \n"
|
||||||
|
" float fresnel = abs(dot(normalize(EyeDir), Normal)); \n"
|
||||||
|
" fresnel *= MixRatio; \n"
|
||||||
|
" fresnel = clamp(fresnel, 0.1, 0.9); \n"
|
||||||
|
" \n"
|
||||||
|
" // calc refraction \n"
|
||||||
|
" vec3 refractionDir = normalize(EyeDir) - normalize(Normal); \n"
|
||||||
|
" \n"
|
||||||
|
" // Scale the refraction so the z element is equal to depth \n"
|
||||||
|
" float depthVal = Depth / -refractionDir.z; \n"
|
||||||
|
" \n"
|
||||||
|
" // perform the div by w \n"
|
||||||
|
" float recipW = 1.0 / EyePos.w; \n"
|
||||||
|
" vec2 eye = EyePos.xy * vec2(recipW); \n"
|
||||||
|
" \n"
|
||||||
|
" // calc the refraction lookup \n"
|
||||||
|
" index.s = (eye.x + refractionDir.x * depthVal); \n"
|
||||||
|
" index.t = (eye.y + refractionDir.y * depthVal); \n"
|
||||||
|
" \n"
|
||||||
|
" // scale and shift so we're in the range 0-1 \n"
|
||||||
|
" index.s = index.s / 2.0 + 0.5; \n"
|
||||||
|
" index.t = index.t / 2.0 + 0.5; \n"
|
||||||
|
" \n"
|
||||||
|
" // as we're looking at the framebuffer, we want it clamping at the edge of the rendered scene, not the edge of the texture, \n"
|
||||||
|
" // so we clamp before scaling to fit \n"
|
||||||
|
" float recip1k = 1.0 / 255.0; \n"
|
||||||
|
" index.s = clamp(index.s, 0.0, 1.0 - recip1k); \n"
|
||||||
|
" index.t = clamp(index.t, 0.0, 1.0 - recip1k); \n"
|
||||||
|
" \n"
|
||||||
|
" // scale the texture so we just see the rendered framebuffer \n"
|
||||||
|
" index.s = index.s * FrameWidth * recip1k; \n"
|
||||||
|
" index.t = index.t * FrameHeight * recip1k; \n"
|
||||||
|
" \n"
|
||||||
|
" vec3 RefractionColor = vec3 (texture2D(RefractionMap, index)); \n"
|
||||||
|
" \n"
|
||||||
|
" // Add lighting to base color and mix \n"
|
||||||
|
" vec3 base = LightIntensity * BaseColor; \n"
|
||||||
|
" envColor = mix(envColor, RefractionColor, fresnel); \n"
|
||||||
|
" envColor = mix(envColor, base, 0.2); \n"
|
||||||
|
" \n"
|
||||||
|
" gl_FragColor = vec4 (envColor, 1.0); \n"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
irr::core::array<rc_shader_material_obj> rc_shader_materials;
|
||||||
|
|
||||||
|
void init_refraction1()
|
||||||
|
{
|
||||||
|
rc_shader_material_obj shader_material;
|
||||||
|
|
||||||
|
rc_shader_obj obj;
|
||||||
|
|
||||||
|
obj.name = "BaseColor";
|
||||||
|
obj.type = "vec3";
|
||||||
|
obj.fragVar = true;
|
||||||
|
obj.artistVar = true;
|
||||||
|
obj.value.push_back(rc_shader_float(0.40000));
|
||||||
|
obj.value.push_back(rc_shader_float(0.40000));
|
||||||
|
obj.value.push_back(rc_shader_float(0.10000));
|
||||||
|
shader_material.shader_object.push_back(obj);
|
||||||
|
obj.value.clear();
|
||||||
|
obj.additional_value.clear();
|
||||||
|
|
||||||
|
obj.name = "Depth";
|
||||||
|
obj.type = "float";
|
||||||
|
obj.fragVar = true;
|
||||||
|
obj.artistVar = true;
|
||||||
|
obj.value.push_back(rc_shader_float(0.10000));
|
||||||
|
shader_material.shader_object.push_back(obj);
|
||||||
|
obj.value.clear();
|
||||||
|
obj.additional_value.clear();
|
||||||
|
|
||||||
|
obj.name = "MixRatio";
|
||||||
|
obj.type = "float";
|
||||||
|
obj.fragVar = true;
|
||||||
|
obj.artistVar = true;
|
||||||
|
obj.value.push_back(rc_shader_float(1.0000));
|
||||||
|
shader_material.shader_object.push_back(obj);
|
||||||
|
obj.value.clear();
|
||||||
|
obj.additional_value.clear();
|
||||||
|
|
||||||
|
obj.name = "FrameHeight";
|
||||||
|
obj.type = "float";
|
||||||
|
obj.fragVar = true;
|
||||||
|
obj.artistVar = false;
|
||||||
|
obj.value.push_back(rc_shader_float(255.0000));
|
||||||
|
shader_material.shader_object.push_back(obj);
|
||||||
|
obj.value.clear();
|
||||||
|
obj.additional_value.clear();
|
||||||
|
|
||||||
|
obj.name = "FrameWidth";
|
||||||
|
obj.type = "float";
|
||||||
|
obj.fragVar = true;
|
||||||
|
obj.artistVar = false;
|
||||||
|
obj.value.push_back(rc_shader_float(255.0000));
|
||||||
|
shader_material.shader_object.push_back(obj);
|
||||||
|
obj.value.clear();
|
||||||
|
obj.additional_value.clear();
|
||||||
|
|
||||||
|
obj.name = "EnvMap";
|
||||||
|
obj.type = "sampler2d";
|
||||||
|
obj.fragVar = true;
|
||||||
|
obj.artistVar = false;
|
||||||
|
obj.value.push_back(rc_shader_float(0));
|
||||||
|
shader_material.shader_object.push_back(obj);
|
||||||
|
obj.value.clear();
|
||||||
|
obj.additional_value.clear();
|
||||||
|
|
||||||
|
obj.name = "RefractionMap";
|
||||||
|
obj.type = "predefined";
|
||||||
|
obj.fragVar = true;
|
||||||
|
obj.artistVar = false;
|
||||||
|
obj.value.push_back(rc_shader_string("predefined_rtt_view"));
|
||||||
|
obj.additional_value.push_back(rc_shader_float(1));
|
||||||
|
shader_material.shader_object.push_back(obj);
|
||||||
|
obj.value.clear();
|
||||||
|
obj.additional_value.clear();
|
||||||
|
|
||||||
|
shader_material.frag_shader = refraction1_frag;
|
||||||
|
shader_material.vert_shader = refraction1_vert;
|
||||||
|
|
||||||
|
rc_shader_materials.push_back(shader_material);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string refraction2_frag;
|
||||||
|
std::string refraction2_vert;
|
||||||
|
|
||||||
|
void init_refraction2()
|
||||||
|
{
|
||||||
|
rc_shader_material_obj shader_material;
|
||||||
|
|
||||||
|
shader_material.frag_shader = refraction2_frag;
|
||||||
|
shader_material.vert_shader = refraction2_vert;
|
||||||
|
|
||||||
|
rc_shader_materials.push_back(shader_material);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Now we have to set up a simple Render-To-Texture management
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
//scenenode_for_rtt_view:
|
||||||
|
//Here all scenenodes get stored which use a shader with RTT requirement.
|
||||||
|
//This is currently just the glass refraction shader
|
||||||
|
core::array<scene::ISceneNode*> scenenodes_for_rtt_view;
|
||||||
|
|
||||||
|
//tex_rtt_view:
|
||||||
|
//The texture which holds the texture render from the view position.
|
||||||
|
//There's currently no other RTT-type supported. Each type would need
|
||||||
|
//its own texture.
|
||||||
|
video::ITexture* tex_rtt_view = 0;
|
||||||
|
|
||||||
|
|
||||||
|
//Adds a scenenode to the RTT-queue if it has a RTT-requirement
|
||||||
|
//These information are all provided and handled by the DynamicShader files.
|
||||||
|
void registerSceneNodeForRTT(scene::ISceneNode* node, S_RTT_Info* rtt_info)
|
||||||
|
{
|
||||||
|
if(node && rtt_info)
|
||||||
|
{
|
||||||
|
switch(rtt_info->type)
|
||||||
|
{
|
||||||
|
case ERT_VIEW:
|
||||||
|
{
|
||||||
|
if(scenenodes_for_rtt_view.size() <= 0)
|
||||||
|
tex_rtt_view = driver->addRenderTargetTexture( core::dimension2d<u32>(256,256) );
|
||||||
|
|
||||||
|
scenenodes_for_rtt_view.push_back(node);
|
||||||
|
node->setMaterialTexture(rtt_info->tex_channel,tex_rtt_view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
//again simple Irrlicht setup/loading stuff
|
||||||
|
device = createDevice(video::EDT_OPENGL, core::dimension2d<u32>(800,600));
|
||||||
|
if(!device) return -1;
|
||||||
|
|
||||||
|
driver = device->getVideoDriver();
|
||||||
|
if(!driver) return -2;
|
||||||
|
|
||||||
|
smgr = device->getSceneManager();
|
||||||
|
if(!smgr) return -3;
|
||||||
|
|
||||||
|
cam = smgr->addCameraSceneNodeMaya();
|
||||||
|
|
||||||
|
device->setWindowCaption(L"Dynamic Shader Example - Masterhawk studios 2011");
|
||||||
|
|
||||||
|
|
||||||
|
//loading the angel model
|
||||||
|
scene::ISceneNode* glass_angel = smgr->addMeshSceneNode(smgr->getMesh("./meshes/statue_angel.obj"));
|
||||||
|
//setting up the environment texture for the simulated reflection.
|
||||||
|
//In IrrShaderViewer this is achieved by the settings xml files.
|
||||||
|
glass_angel->setMaterialTexture(0,driver->getTexture("./media/House.jpg"));
|
||||||
|
|
||||||
|
//disable lighting. This shader doesn't need a light source
|
||||||
|
glass_angel->setMaterialFlag(video::EMF_LIGHTING,false);
|
||||||
|
|
||||||
|
//loading the shader-defintion and create a shader. Don't forget to delete
|
||||||
|
//the pointer!
|
||||||
|
init_refraction1();
|
||||||
|
CShader* glass_shader = new CShader(device, rc_shader_materials[0]);
|
||||||
|
|
||||||
|
//assigning the shader to the scenenode
|
||||||
|
if(glass_shader)
|
||||||
|
glass_angel->setMaterialType((video::E_MATERIAL_TYPE)glass_shader->getMaterial());
|
||||||
|
|
||||||
|
//register the scenenode for RTT handling. This is made for every scenenode, no
|
||||||
|
//matter if its shader requires RTT support or not. The registerSceneNodeForRTT()
|
||||||
|
//takes care of this
|
||||||
|
registerSceneNodeForRTT(glass_angel,glass_shader->getRTTInfo(ERT_VIEW));
|
||||||
|
|
||||||
|
//adding a skybox so you can see a transparency effect
|
||||||
|
smgr->addSkyBoxSceneNode(
|
||||||
|
driver->getTexture("./media/irrlicht2_up.jpg"),
|
||||||
|
driver->getTexture("./media/irrlicht2_dn.jpg"),
|
||||||
|
driver->getTexture("./media/irrlicht2_lf.jpg"),
|
||||||
|
driver->getTexture("./media/irrlicht2_rt.jpg"),
|
||||||
|
driver->getTexture("./media/irrlicht2_ft.jpg"),
|
||||||
|
driver->getTexture("./media/irrlicht2_bk.jpg"));
|
||||||
|
|
||||||
|
while(device->run())
|
||||||
|
{
|
||||||
|
driver->beginScene(true, true, video::SColor(255,100,100,100));
|
||||||
|
|
||||||
|
//creating the RTT-VIEW texture for every frame
|
||||||
|
if(scenenodes_for_rtt_view.size() > 0)
|
||||||
|
{
|
||||||
|
for(s32 i=0; i<scenenodes_for_rtt_view.size(); i++)
|
||||||
|
scenenodes_for_rtt_view[i]->setVisible(false);
|
||||||
|
|
||||||
|
driver->setRenderTarget(tex_rtt_view);
|
||||||
|
smgr->drawAll();
|
||||||
|
driver->setRenderTarget(0);
|
||||||
|
|
||||||
|
for(s32 i=0; i<scenenodes_for_rtt_view.size(); i++)
|
||||||
|
scenenodes_for_rtt_view[i]->setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//just the normal rendering
|
||||||
|
smgr->drawAll();
|
||||||
|
driver->endScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
device->drop();
|
||||||
|
|
||||||
|
//deleting the shader
|
||||||
|
delete glass_shader;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user