Clip shadow above ball with a texture
authorparasti <parasti@78b8d119-cf0a-0410-b17c-f493084dd1d7>
Sun, 13 Mar 2011 17:58:07 +0000 (17:58 +0000)
committerparasti <parasti@78b8d119-cf0a-0410-b17c-f493084dd1d7>
Sun, 13 Mar 2011 17:58:07 +0000 (17:58 +0000)
Requires ARB_multitexture, but tries hard to be optional.

git-svn-id: https://s.snth.net/svn/neverball/trunk@3522 78b8d119-cf0a-0410-b17c-f493084dd1d7

share/geom.c
share/glext.h
share/solid_draw.c
share/video.c

index 920c0b5..5d8ab3e 100644 (file)
@@ -290,6 +290,71 @@ void flag_draw(void)
 }
 
 /*---------------------------------------------------------------------------*/
+
+static GLuint clip_text;
+
+static GLubyte clip_data[] = { 0xff, 0xff, 0x0, 0x0 };
+
+void clip_init(void)
+{
+    if (!glActiveTextureARB_)
+        return;
+
+    glActiveTextureARB_(GL_TEXTURE1_ARB);
+    {
+        glGenTextures(1, &clip_text);
+        glBindTexture(GL_TEXTURE_1D, clip_text);
+
+        glTexImage1D(GL_TEXTURE_1D, 0,
+                     GL_LUMINANCE_ALPHA, 2, 0,
+                     GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, clip_data);
+
+        glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+        glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+    }
+    glActiveTextureARB_(GL_TEXTURE0_ARB);
+}
+
+void clip_free(void)
+{
+    if (glIsTexture(clip_text))
+        glDeleteTextures(1, &clip_text);
+}
+
+void clip_draw_set(void)
+{
+    if (!glActiveTextureARB_)
+        return;
+
+    glActiveTextureARB_(GL_TEXTURE1_ARB);
+    {
+        glBindTexture(GL_TEXTURE_1D, clip_text);
+
+        glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+
+        glEnable(GL_TEXTURE_GEN_S);
+        glEnable(GL_TEXTURE_1D);
+    }
+    glActiveTextureARB_(GL_TEXTURE0_ARB);
+}
+
+void clip_draw_clr(void)
+{
+    if (!glActiveTextureARB_)
+        return;
+
+    glActiveTextureARB_(GL_TEXTURE1_ARB);
+    {
+        glDisable(GL_TEXTURE_GEN_S);
+        glDisable(GL_TEXTURE_1D);
+    }
+    glActiveTextureARB_(GL_TEXTURE0_ARB);
+}
+
+/*---------------------------------------------------------------------------*/
+
 /*
  * A note about lighting and shadow: technically speaking, it's wrong.
  * The  light  position  and   shadow  projection  behave  as  if  the
@@ -314,12 +379,16 @@ void shad_init(void)
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
     }
+
+    clip_init();
 }
 
 void shad_free(void)
 {
     if (glIsTexture(shad_text))
         glDeleteTextures(1, &shad_text);
+
+    clip_free();
 }
 
 void shad_draw_set(void)
@@ -337,12 +406,16 @@ void shad_draw_set(void)
 
     glEnable(GL_TEXTURE_GEN_S);
     glEnable(GL_TEXTURE_GEN_T);
+
+    clip_draw_set();
 }
 
 void shad_draw_clr(void)
 {
     glDisable(GL_TEXTURE_GEN_S);
     glDisable(GL_TEXTURE_GEN_T);
+
+    clip_draw_clr();
 }
 
 /*---------------------------------------------------------------------------*/
index 85a2ba3..7a12b9e 100644 (file)
 
 /*---------------------------------------------------------------------------*/
 
+#ifndef GL_ARB_multitexture
+#define GL_TEXTURE0_ARB                   0x84C0
+#define GL_TEXTURE1_ARB                   0x84C1
+
+typedef void (*PFNGLACTIVETEXTUREARBPROC)(GLenum);
+#endif
+
+extern PFNGLACTIVETEXTUREARBPROC glActiveTextureARB_;
+
+/*---------------------------------------------------------------------------*/
+
 #endif
index bc8b0e7..5cab6d3 100644 (file)
@@ -527,6 +527,7 @@ static void sol_shad_list(const struct s_vary *vary,
     float d[3];
 
     float X[] = { 1.0f, 0.0f, 0.0f, 0.0f };
+    float Y[] = { 0.0f, 1.0f, 0.0f, 0.0f };
     float Z[] = { 0.0f, 0.0f, 1.0f, 0.0f };
 
     sol_body_p(p, vary, bp->pi, bp->t);
@@ -534,13 +535,17 @@ static void sol_shad_list(const struct s_vary *vary,
 
     v_sub(d, up->p, p);
 
+    Y[3] = 0.5f - v_dot(Y, d);
+
     if (e[0] != 1.0f)
     {
         q_as_axisangle(e, u, &a);
         a = V_DEG(a);
 
         q_conj(e, e);
+
         q_rot(X, e, X);
+        q_rot(Y, e, Y);
         q_rot(Z, e, Z);
     }
     else
@@ -568,6 +573,15 @@ static void sol_shad_list(const struct s_vary *vary,
     }
     glMatrixMode(GL_MODELVIEW);
 
+    /* Set up shadow clipping. */
+
+    if (glActiveTextureARB_)
+    {
+        glActiveTextureARB_(GL_TEXTURE1_ARB);
+        glTexGenfv(GL_S, GL_OBJECT_PLANE, Y);
+        glActiveTextureARB_(GL_TEXTURE0_ARB);
+    }
+
     /* Draw the body. */
 
     glPushMatrix();
index 36e626a..8d9b23a 100644 (file)
@@ -56,6 +56,8 @@ int video_init(const char *title, const char *icon)
 
 /*---------------------------------------------------------------------------*/
 
+PFNGLACTIVETEXTUREARBPROC glActiveTextureARB_;
+
 int check_extension(const char *needle)
 {
     const GLubyte *haystack, *c;
@@ -133,6 +135,18 @@ int video_mode(int f, int w, int h)
         }
 #endif
 
+        if (check_extension("ARB_multitexture"))
+        {
+            union
+            {
+                void *ob;
+                PFNGLACTIVETEXTUREARBPROC fn;
+            } cast;
+
+            cast.ob = SDL_GL_GetProcAddress("glActiveTextureARB");
+            glActiveTextureARB_ = cast.fn;
+        }
+
         glReadBuffer(GL_FRONT);
 
         /* Attempt manual swap control if SDL's is broken. */