+++ /dev/null
-/* vi: set ft=glsl */
-#ifdef USE_CUBEMAP
-uniform samplerCube envmap;
-#endif
-uniform sampler2DShadow shadowmap;
-
-varying vec3 vdir, ldir[3], normal;
-varying vec4 shadow_tc;
-varying vec3 wdir;
-
-#define KD gl_FrontMaterial.diffuse.rgb
-#define KS gl_FrontMaterial.specular.rgb
-#define SPOW gl_FrontMaterial.shininess
-
-#define LD(i) gl_LightSource[i].diffuse.rgb
-#define LS(i) gl_LightSource[i].specular.rgb
-
-vec3 calc_diffuse(in vec3 n, in vec3 l, in vec3 lcol)
-{
- float ndotl = max(dot(n, l), 0.0);
- return KD * lcol * ndotl;
-}
-
-vec3 calc_specular(in vec3 n, in vec3 l, in vec3 v, in vec3 lcol)
-{
- vec3 h = normalize(l + v);
- float ndoth = max(dot(n, h), 0.0);
- return KS * lcol * pow(ndoth, SPOW);
-}
-
-void main()
-{
- float shadow = shadow2DProj(shadowmap, shadow_tc).x;
-
- vec3 n = normalize(normal);
- vec3 v = normalize(vdir);
-
- vec3 l = normalize(ldir[0]);
- vec3 diffuse = calc_diffuse(n, l, LD(0)) * shadow;
- vec3 specular = calc_specular(n, l, v, LS(0)) * shadow;
-
- l = normalize(ldir[1]);
- diffuse += calc_diffuse(n, l, LD(1));
- specular += calc_specular(n, l, v, LS(1));
-
- l = normalize(ldir[2]);
- diffuse += calc_diffuse(n, l, LD(2));
- specular += calc_specular(n, l, v, LS(2));
-
-#ifdef USE_CUBEMAP
- // envmap
- vec3 rdir = -reflect(wdir, n);
- vec3 env_texel = textureCube(envmap, rdir).xyz;
- specular += KS * env_texel;
-#endif // USE_CUBEMAP
-
- vec3 ambient = gl_LightModel.ambient.rgb * KD;
- gl_FragColor.rgb = ambient + diffuse + specular;
- gl_FragColor.a = gl_FrontMaterial.diffuse.a;
-}
+++ /dev/null
-uniform mat4 envmap_matrix;
-
-varying vec3 vdir, ldir[3], normal;
-varying vec4 shadow_tc;
-varying vec3 wdir;
-
-void main()
-{
- gl_Position = ftransform();
-
- vec3 vpos = (gl_ModelViewMatrix * gl_Vertex).xyz;
- normal = gl_NormalMatrix * gl_Normal;
- vdir = -vpos;
- wdir = (envmap_matrix * vec4(vdir, 1.0)).xyz; // bring back to world space
- ldir[0] = gl_LightSource[0].position.xyz - vpos;
- ldir[1] = gl_LightSource[1].position.xyz - vpos;
- ldir[2] = gl_LightSource[2].position.xyz - vpos;
- gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
-
- mat4 offmat = mat4(0.5, 0.0, 0.0, 0.0,
- 0.0, 0.5, 0.0, 0.0,
- 0.0, 0.0, 0.5, 0.0,
- 0.5, 0.5, 0.5, 1.0);
- mat4 tex_matrix = offmat * gl_TextureMatrix[1];
-
- shadow_tc = tex_matrix * vec4(vpos, 1.0);
-}
--- /dev/null
+/* vi:set ft=glsl: */
+#ifdef USE_TEXMAP
+uniform sampler2D texmap;
+#endif
+#ifdef USE_CUBEMAP
+uniform samplerCube envmap;
+#endif
+#ifdef USE_SHADOWMAP
+uniform sampler2DShadow shadowmap;
+#endif
+
+varying vec3 vpos, vdir, normal;
+#ifdef USE_SHADOWMAP
+varying vec4 shadow_tc;
+#endif
+#ifdef USE_CUBEMAP
+varying vec3 wdir;
+#endif
+
+#ifdef USE_TEXMAP
+#define KD texel.rgb
+#else
+#define KD gl_FrontMaterial.diffuse.rgb
+#endif
+
+#define KS gl_FrontMaterial.specular.rgb
+#define SPOW gl_FrontMaterial.shininess
+
+#define LD(i) gl_LightSource[i].diffuse.rgb
+#define LS(i) gl_LightSource[i].specular.rgb
+#define LPOS(i) gl_LightSource[i].position.xyz
+
+vec3 calc_diffuse(in vec3 n, in vec3 l, in vec3 color, in vec3 lcol)
+{
+ float ndotl = max(dot(n, l), 0.0);
+ return color * lcol * ndotl;
+}
+
+vec3 calc_specular(in vec3 n, in vec3 l, in vec3 v, in vec3 color, in vec3 lcol)
+{
+ vec3 h = normalize(l + v);
+ float ndoth = max(dot(n, h), 0.0);
+ return color * lcol * pow(ndoth, SPOW);
+}
+
+
+void main()
+{
+#ifdef USE_TEXMAP
+ vec4 texel = texture2D(texmap, gl_TexCoord[0].st);
+#endif
+#ifdef USE_SHADOWMAP
+ float shadow = shadow2DProj(shadowmap, shadow_tc).x;
+#else
+ const float shadow = 1.0;
+#endif
+
+ vec3 n = normalize(normal);
+ vec3 v = normalize(vdir);
+
+ vec3 diffuse = vec3(0.0, 0.0, 0.0);
+ vec3 specular = vec3(0.0, 0.0, 0.0);
+
+#ifdef USE_LIGHT0
+ {
+ vec3 l = normalize(LPOS(0) - vpos);
+ diffuse += calc_diffuse(n, l, KD, LD(0)) * shadow;
+ specular += calc_specular(n, l, v, KS, LS(0)) * shadow;
+ }
+#endif
+#ifdef USE_LIGHT1
+ {
+ vec3 l = normalize(LPOS(1) - vpos);
+ diffuse += calc_diffuse(n, l, KD, LD(1)) * shadow;
+ specular += calc_specular(n, l, v, KS, LS(1)) * shadow;
+ }
+#endif
+#ifdef USE_LIGHT2
+ {
+ vec3 l = normalize(LPOS(2) - vpos);
+ diffuse += calc_diffuse(n, l, KD, LD(2)) * shadow;
+ specular += calc_specular(n, l, v, KS, LS(2)) * shadow;
+ }
+#endif
+
+#ifdef USE_CUBEMAP
+ // envmap
+ vec3 rdir = -reflect(wdir, n);
+ vec3 env_texel = textureCube(envmap, rdir).xyz;
+ specular += KS * env_texel;
+#endif // USE_CUBEMAP
+
+ vec3 ambient = gl_LightModel.ambient.rgb * KD;
+ gl_FragColor.rgb = ambient + diffuse + specular;
+#ifdef USE_TEXMAP
+ gl_FragColor.a = gl_FrontMaterial.diffuse.a * texel.a;
+#else
+ gl_FragColor.a = gl_FrontMaterial.diffuse.a;
+#endif
+}
--- /dev/null
+varying vec3 vpos, vdir, normal;
+#ifdef USE_SHADOWMAP
+varying vec4 shadow_tc;
+#endif
+#ifdef USE_CUBEMAP
+varying vec3 wdir;
+uniform mat4 envmap_matrix;
+#endif
+
+void main()
+{
+ gl_Position = ftransform();
+
+ vpos = (gl_ModelViewMatrix * gl_Vertex).xyz;
+ normal = gl_NormalMatrix * gl_Normal;
+ vdir = -vpos;
+#ifdef USE_CUBEMAP
+ wdir = (envmap_matrix * vec4(vdir, 1.0)).xyz; // bring back to world space
+#endif
+#ifdef USE_TEXMAP
+ gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+#endif
+
+#ifdef USE_SHADOWMAP
+ mat4 offmat = mat4(0.5, 0.0, 0.0, 0.0,
+ 0.0, 0.5, 0.0, 0.0,
+ 0.0, 0.0, 0.5, 0.0,
+ 0.5, 0.5, 0.5, 1.0);
+ mat4 tex_matrix = offmat * gl_TextureMatrix[1];
+
+ shadow_tc = tex_matrix * vec4(vpos, 1.0);
+#endif
+}
#include "app.h"
#include "opengl.h"
#include "sdr.h"
+#include "ubersdr.h"
#include "texture.h"
#include "mesh.h"
#include "meshgen.h"
static void draw_scene();
static void toggle_flight();
static void calc_framerate();
+static void prebake_shaders();
long time_msec;
int win_width, win_height;
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glEnable(GL_NORMALIZE);
+ glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
Mesh::use_custom_sdr_attr = false;
- float ambient[] = {0.0, 0.0, 0.0, 0.0};
+ float ambient[] = {0.02, 0.02, 0.02, 0.0};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
glClearColor(0.1, 0.1, 0.1, 1.0);
blobs->node->set_scaling(Vec3(0.1, 0.1, 0.1));
blobs->node->update(0);
+ if(uber_init("sdr/uber.v.glsl", "sdr/uber.p.glsl") == -1) {
+ return false;
+ }
+ prebake_shaders();
+ /*
if(!(sdr_shadow_notex = create_program_load("sdr/shadow.v.glsl", "sdr/shadow-notex.p.glsl"))) {
return false;
}
set_uniform_int(sdr_shadow_notex, "shadowmap", 1);
set_uniform_int(sdr_shadow_notex, "envmap", 2);
+ */
if(!fb_srgb) {
sdr_post_gamma = create_program_load("sdr/post_gamma.v.glsl", "sdr/post_gamma.p.glsl");
glLightfv(lt, GL_POSITION, posv);
glLightfv(lt, GL_DIFFUSE, colv);
glLightfv(lt, GL_SPECULAR, colv);
+
+ uber_enable_light(idx);
}
void app_display()
{
static const Vec3 lpos[] = { Vec3(-50, 75, 100), Vec3(100, 0, 30), Vec3(-10, -10, 60) };
set_light(0, lpos[0], Vec3(1.0, 0.8, 0.7) * 0.8);
- set_light(1, lpos[1], Vec3(0.6, 0.7, 1.0) * 0.6);
- set_light(2, lpos[2], Vec3(0.8, 1.0, 0.8) * 0.3);
+ //set_light(1, lpos[1], Vec3(0.6, 0.7, 1.0) * 0.6);
+ //set_light(2, lpos[2], Vec3(0.8, 1.0, 0.8) * 0.3);
mscn->draw();
if(show_blobs) {
++nframes;
}
}
+
+static void prebake_shaders()
+{
+ /*
+ unsigned int prog;
+
+ uber_clear();
+ uber_enable_light(0);
+ uber_enable_light(1);
+ uber_enable_light(2);
+ if((prog = uber_program())) {
+ }
+
+ uber_enable_texmap();
+ if((prog = uber_program())) {
+ set_uniform_int(prog, "texmap", MTL_TEX_DIFFUSE);
+ }
+
+ uber_clear();
+ */
+}
static char *clean_line(char *s);
+DataMap::DataMap()
+{
+ strip_paths = false;
+}
+
void DataMap::clear()
{
dmap.clear();
root = std::string(path);
}
+void DataMap::set_strip(bool s)
+{
+ strip_paths = s;
+}
+
bool DataMap::load_map(const char *fname)
{
std::string path = root.empty() ? fname : root + std::string("/") + fname;
{
std::string res;
+ if(strip_paths) {
+ const char *ptr = strrchr(in, '/');
+ if(ptr) {
+ in = ptr + 1;
+ }
+ }
+
char *inbuf = (char*)alloca(strlen(in) + 1);
strcpy(inbuf, in);
in = clean_line(inbuf);
std::vector<std::pair<std::string, std::string>> dmap;
mutable std::map<std::string, std::string> cache;
std::string root;
+ bool strip_paths;
public:
+ DataMap();
+
void clear();
void set_path(const char *path);
+ void set_strip(bool s);
bool load_map(const char *fname);
void map(const char *match, const char *path);
#include "material.h"
#include "sdr.h"
#include "app.h"
+#include "ubersdr.h"
Material::Material()
: diffuse(1.0f, 1.0f, 1.0f)
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, ks);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
- int ntex = std::min((int)textures.size(), 8); // TODO: use max texture units
- for(int i=0; i<ntex; i++) {
- bind_texture(textures[i], i);
+ for(int i=0; i<NUM_MTL_TEXTURES; i++) {
+ bind_texture(stdtex[i], i);
}
- /*
- if(stdtex[MTL_TEX_LIGHTMAP]) {
- bind_program(stdtex[MTL_TEX_DIFFUSE] ? sdr_ltmap : sdr_ltmap_notex);
+ if(stdtex[MTL_TEX_DIFFUSE]) {
+ uber_enable_texmap();
+ } else {
+ uber_disable_texmap();
+ }
+ if(stdtex[MTL_TEX_ENVMAP] && stdtex[MTL_TEX_ENVMAP]->get_type() == TEX_CUBE) {
+ uber_enable_cubemap();
+ } else {
+ uber_disable_cubemap();
}
- */
+ if(stdtex[MTL_TEX_ENVMAP] && stdtex[MTL_TEX_ENVMAP]->get_type() == TEX_2D) {
+ uber_enable_sphmap();
+ } else {
+ uber_disable_sphmap();
+ }
+ /* TODO shadows */
+
+ unsigned int sdrprog = uber_program();
+ bind_program(sdrprog);
}
void Material::add_texture(Texture *tex, int type)
// datapath
struct ts_attr *adpath = attr_inscope(node, "datapath");
if(adpath && adpath->val.type == TS_STRING) {
- info_log("adding data path: %s\n", adpath->val.str);
mscn->datamap.set_path(adpath->val.str);
}
+ // strip path
+ struct ts_attr *aspath = attr_inscope(node, "strip_path");
+ if(aspath && aspath->val.type == TS_NUMBER) {
+ mscn->datamap.set_strip(aspath->val.inum);
+ }
+
// walkmesh
struct ts_attr *awmesh = attr_inscope(node, "walkmesh");
if(awmesh && awmesh->val.type == TS_STRING) {
--- /dev/null
+#include <stdlib.h>
+#include <string.h>
+#include <opengl.h>
+#include <logger.h>
+#include "ubersdr.h"
+#include "sdr.h"
+
+enum {
+ UBER_LIGHT0,
+ UBER_LIGHT1,
+ UBER_LIGHT2,
+ UBER_LIGHT3,
+ UBER_TEXMAP,
+ UBER_CUBEMAP,
+ UBER_SPHMAP,
+ UBER_SHADOWS,
+
+ MAX_STATE_BITS
+};
+#define MAX_LIGHTS 4
+
+static const char *macros[] = {
+ "#define USE_LIGHT0\n",
+ "#define USE_LIGHT1\n",
+ "#define USE_LIGHT2\n",
+ "#define USE_LIGHT3\n",
+ "#define USE_TEXMAP\n",
+ "#define USE_CUBEMAP\n",
+ "#define USE_SPHMAP\n",
+ "#define USE_SHADOWMAP\n",
+ 0
+};
+
+struct sdrcache {
+ unsigned int vs, ps;
+ unsigned int prog;
+};
+
+static unsigned int mkshader(unsigned int type);
+
+static char *vs_fname, *ps_fname;
+static unsigned int state;
+
+#define CACHE_SIZE (1 << MAX_STATE_BITS)
+static struct sdrcache cache[CACHE_SIZE];
+
+int uber_init(const char *vsname, const char *psname)
+{
+ state = 0;
+ memset(cache, 0, sizeof cache);
+
+ vs_fname = strdup(vsname);
+ ps_fname = strdup(psname);
+ if(!vs_fname || !ps_fname) {
+ free(vs_fname);
+ return -1;
+ }
+ return 0;
+}
+
+void uber_destroy(void)
+{
+ int i;
+
+ for(i=0; i<CACHE_SIZE; i++) {
+ if(cache[i].vs)
+ free_shader(cache[i].vs);
+ if(cache[i].ps)
+ free_shader(cache[i].ps);
+ if(cache[i].prog)
+ free_program(cache[i].prog);
+ }
+ free(vs_fname);
+ free(ps_fname);
+}
+
+void uber_clear(void)
+{
+ state = 0;
+}
+
+void uber_enable_light(int idx)
+{
+ if(idx >= 0 && idx < MAX_LIGHTS) {
+ state |= (1 << (UBER_LIGHT0 + idx));
+ }
+}
+
+void uber_disable_light(int idx)
+{
+ if(idx >= 0 && idx < MAX_LIGHTS) {
+ state &= ~(1 << (UBER_LIGHT0 + idx));
+ }
+}
+
+void uber_enable_texmap(void)
+{
+ state |= (1 << UBER_TEXMAP);
+}
+
+void uber_disable_texmap(void)
+{
+ state &= ~(1 << UBER_TEXMAP);
+}
+
+void uber_enable_cubemap(void)
+{
+ state |= (1 << UBER_CUBEMAP);
+}
+
+void uber_disable_cubemap(void)
+{
+ state &= ~(1 << UBER_CUBEMAP);
+}
+
+void uber_enable_sphmap(void)
+{
+ state |= (1 << UBER_SPHMAP);
+}
+
+void uber_disable_sphmap(void)
+{
+ state &= ~(1 << UBER_SPHMAP);
+}
+
+void uber_enable_shadows(void)
+{
+ state |= (1 << UBER_SHADOWS);
+}
+
+void uber_disable_shadows(void)
+{
+ state &= ~(1 << UBER_SHADOWS);
+}
+
+unsigned int uber_vertex_shader(void)
+{
+ if(!cache[state].vs) {
+ cache[state].vs = mkshader(GL_VERTEX_SHADER);
+ }
+ return cache[state].vs;
+}
+
+unsigned int uber_pixel_shader(void)
+{
+ if(!cache[state].ps) {
+ cache[state].ps = mkshader(GL_FRAGMENT_SHADER);
+ }
+ return cache[state].ps;
+}
+
+static unsigned int mkshader(unsigned int type)
+{
+ int i;
+ unsigned int res;
+ clear_shader_header(type);
+
+ debug_log("mkshader(%s): %x\n", type == GL_VERTEX_SHADER ? "vertex" : "pixel");
+
+ for(i=0; i<MAX_STATE_BITS; i++) {
+ if(state & (1 << i)) {
+ add_shader_header(type, macros[i]);
+ debug_log(" - header: %s\n", macros[i]);
+ }
+ }
+ res = load_shader(type == GL_VERTEX_SHADER ? vs_fname : ps_fname, type);
+ clear_shader_header(type);
+ return res;
+}
+
+unsigned int uber_program(void)
+{
+ if(!cache[state].prog) {
+ unsigned int vs, ps;
+ if(!(vs = uber_vertex_shader()) || !(ps = uber_pixel_shader())) {
+ error_log("uber_program failed to make shaders for state: %x\n", state);
+ return 0;
+ }
+ if(!(cache[state].prog = create_program_link(vs, ps, 0))) {
+ error_log("uber_program failed to link program for state: %x\n", state);
+ return 0;
+ }
+ }
+ return cache[state].prog;
+}
--- /dev/null
+#ifndef UBERSDR_H_
+#define UBERSDR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int uber_init(const char *vsname, const char *psname);
+void uber_destroy(void);
+
+void uber_clear(void);
+
+void uber_enable_light(int idx);
+void uber_disable_light(int idx);
+
+void uber_enable_texmap(void);
+void uber_disable_texmap(void);
+
+void uber_enable_cubemap(void);
+void uber_disable_cubemap(void);
+
+void uber_enable_sphmap(void);
+void uber_disable_sphmap(void);
+
+void uber_enable_shadows(void);
+void uber_disable_shadows(void);
+
+unsigned int uber_vertex_shader(void);
+unsigned int uber_pixel_shader(void);
+unsigned int uber_program(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UBERSDR_H_ */