Add 2d texture and GLSL shaders
This commit is contained in:
parent
cad11d37e8
commit
8651f5c205
13 changed files with 506 additions and 181 deletions
|
|
@ -16,6 +16,8 @@
|
|||
extern char errorMessage[256];
|
||||
void setErrorMessage(const char *err);
|
||||
|
||||
int glCheck();
|
||||
|
||||
// opengl font
|
||||
extern void *_fonts;
|
||||
int initText(void);
|
||||
|
|
@ -56,6 +58,18 @@ static PFNGLVERTEXATTRIBPOINTERPROC pglVertexAttribPointer = NULL;
|
|||
|
||||
int initGLExt(void);
|
||||
|
||||
class TextureRect2D {
|
||||
public:
|
||||
GLuint m_id;
|
||||
GLuint m_width;
|
||||
GLuint m_height;
|
||||
GLuint m_depth;
|
||||
TextureRect2D(int width, int height, int depth, void *data);
|
||||
~TextureRect2D();
|
||||
void blit(float x, float y);
|
||||
void copy(GLenum mode);
|
||||
};
|
||||
|
||||
struct ClientBufferAttrib {
|
||||
int enabled;
|
||||
GLenum type;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ cdef extern from "GLTools.h":
|
|||
ctypedef ssize_t GLsizeiptr
|
||||
|
||||
char errorMessage[256]
|
||||
int glCheck()
|
||||
|
||||
int stbi_write_png(char *filename, int w, int h, int comp, void *data, int stride_in_bytes)
|
||||
|
||||
|
|
@ -30,6 +31,14 @@ cdef extern from "GLTools.h":
|
|||
int isGLExtLoaded
|
||||
int c_initGLExt "initGLExt"()
|
||||
|
||||
cdef cppclass c_TextureRect2D "TextureRect2D":
|
||||
GLuint m_width
|
||||
GLuint m_height
|
||||
GLuint m_depth
|
||||
c_TextureRect2D(int width, int height, int depth, void *data)
|
||||
void blit(float x, float y)
|
||||
void copy(GLenum mode)
|
||||
|
||||
cdef cppclass c_ClientBuffer "ClientBuffer":
|
||||
c_ClientBuffer(GLenum target)
|
||||
void bind()
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ cdef extern from "GL/glfw3.h":
|
|||
void glLightf(GLenum light, GLenum pname, GLfloat param)
|
||||
void glLightfv(GLenum light, GLenum pname, GLfloat *params )
|
||||
void glLightModeli(GLenum pname, GLint param)
|
||||
void glLightModelfv(GLenum pname, GLfloat *params)
|
||||
void glLoadIdentity()
|
||||
void glLoadMatrixd(GLdouble *m)
|
||||
void glMaterialfv(GLenum face, GLenum pname, GLfloat *params)
|
||||
|
|
@ -245,6 +246,8 @@ cdef extern from "GL/glfw3.h":
|
|||
GL_POINT
|
||||
GL_LINE
|
||||
GL_FILL
|
||||
GL_POLYGON_OFFSET_LINE
|
||||
GL_POLYGON_OFFSET_FILL
|
||||
|
||||
# ShadingModel
|
||||
GL_FLAT
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ cdef class ClientBuffer:
|
|||
raise GLError('OpenGL 2.1 function pointers not found')
|
||||
|
||||
self.thisptr = new c_ClientBuffer(target)
|
||||
|
||||
if not glCheck():
|
||||
raise GLError(errorMessage)
|
||||
|
||||
def __dealloc__(self):
|
||||
cdef c_ClientBuffer *tmp
|
||||
|
|
|
|||
|
|
@ -143,6 +143,14 @@ cdef class Material:
|
|||
mat[0] = fmin(fmax(0., self.shininess), 128)
|
||||
glMaterialfv(self.mode, GL_SHININESS, mat)
|
||||
|
||||
cpdef ambientLight(ColorRGBA col):
|
||||
'''
|
||||
Set global ambient light color.
|
||||
'''
|
||||
cdef float c_col[4]
|
||||
col.setFloatVector(c_col)
|
||||
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, c_col)
|
||||
|
||||
cdef class Light:
|
||||
'''
|
||||
Abstraction of OpenGL light
|
||||
|
|
|
|||
|
|
@ -159,6 +159,8 @@ LINE_SMOOTH = GL_LINE_SMOOTH
|
|||
POINT = GL_POINT
|
||||
LINE = GL_LINE
|
||||
FILL = GL_FILL
|
||||
POLYGON_OFFSET_LINE = GL_POLYGON_OFFSET_LINE
|
||||
POLYGON_OFFSET_FILL = GL_POLYGON_OFFSET_FILL
|
||||
|
||||
# ShadingModel
|
||||
FLAT = GL_FLAT
|
||||
|
|
|
|||
|
|
@ -14,6 +14,13 @@ cpdef InitGLExt():
|
|||
'''
|
||||
if not c_initGLExt():
|
||||
raise GLError(errorMessage)
|
||||
|
||||
cpdef int Check():
|
||||
'''
|
||||
Check for OpenGL errors
|
||||
'''
|
||||
if not glCheck():
|
||||
raise GLError(errorMessage)
|
||||
|
||||
cpdef BlendFunc(unsigned int sfactor, unsigned int dfactor):
|
||||
'''
|
||||
|
|
@ -86,7 +93,6 @@ cpdef DrawElements(unsigned int mode, int count, int type, indices):
|
|||
try:
|
||||
offset = indices
|
||||
glDrawElements(mode, count, type, <void *>offset)
|
||||
print
|
||||
except TypeError:
|
||||
glDrawElements(mode, count, type, getVoidPtr(indices))
|
||||
|
||||
|
|
@ -95,7 +101,7 @@ cpdef Enable(unsigned int cap):
|
|||
Enable server-side GL capabilities
|
||||
'''
|
||||
glEnable(cap)
|
||||
|
||||
|
||||
cpdef LineWidth(float width):
|
||||
'''
|
||||
Specify the width of rasterized lines
|
||||
|
|
|
|||
|
|
@ -8,6 +8,38 @@ void setErrorMessage(const char *err) {
|
|||
strncpy(errorMessage, err, 255);
|
||||
}
|
||||
|
||||
int glCheck() {
|
||||
switch(glGetError()) {
|
||||
case GL_NO_ERROR:
|
||||
return 1;
|
||||
|
||||
case GL_INVALID_ENUM:
|
||||
setErrorMessage("GL_INVALID_ENUM");
|
||||
break;
|
||||
|
||||
case GL_INVALID_VALUE:
|
||||
setErrorMessage("GL_INVALID_VALUE");
|
||||
break;
|
||||
|
||||
case GL_INVALID_OPERATION:
|
||||
setErrorMessage("GL_INVALID_OPERATION");
|
||||
break;
|
||||
|
||||
case GL_INVALID_FRAMEBUFFER_OPERATION:
|
||||
setErrorMessage("GL_INVALID_FRAMEBUFFER_OPERATION");
|
||||
break;
|
||||
|
||||
case GL_OUT_OF_MEMORY:
|
||||
setErrorMessage("GL_OUT_OF_MEMORY");
|
||||
break;
|
||||
|
||||
default:
|
||||
setErrorMessage("GL_UNKNOWN");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// load font
|
||||
void *_fonts;
|
||||
|
||||
|
|
@ -178,6 +210,83 @@ int initGLExt(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// opengl texture rectangle
|
||||
TextureRect2D::TextureRect2D(int width, int height, int depth, void *data = NULL) {
|
||||
GLint iformat, format;
|
||||
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_depth = depth;
|
||||
|
||||
if (depth == 4) {
|
||||
iformat = GL_RGBA8;
|
||||
format = GL_RGBA;
|
||||
} else {
|
||||
iformat = GL_RGB8;
|
||||
format = GL_RGB;
|
||||
}
|
||||
|
||||
glGenTextures(1, &m_id);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, m_id);
|
||||
|
||||
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
if (!data) {
|
||||
char *colorBits = new char[width * height * depth];
|
||||
memset(colorBits, 0, width * height * depth);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, format, width, height, 0,
|
||||
format, GL_UNSIGNED_BYTE, colorBits);
|
||||
delete[] colorBits;
|
||||
} else {
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, format, width, height, 0,
|
||||
format, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, 0);
|
||||
}
|
||||
|
||||
TextureRect2D::~TextureRect2D() {
|
||||
glDeleteTextures(1, &m_id);
|
||||
}
|
||||
|
||||
void TextureRect2D::blit(float x, float y) {
|
||||
glEnable(GL_TEXTURE_RECTANGLE);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, m_id);
|
||||
glColor3ub(255,255,255);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex3f(x, y, 0);
|
||||
glTexCoord2f(m_width, 0);
|
||||
glVertex3f(x + m_width, y, 0);
|
||||
glTexCoord2f(m_width, m_height);
|
||||
glVertex3f(x + m_width, y + m_height, 0);
|
||||
glTexCoord2f(0, m_height);
|
||||
glVertex3f(x, y + m_height, 0);
|
||||
glEnd();
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, 0);
|
||||
glDisable(GL_TEXTURE_RECTANGLE);
|
||||
}
|
||||
|
||||
void TextureRect2D::copy(GLenum mode = GL_BACK) {
|
||||
glReadBuffer(mode);
|
||||
glEnable(GL_TEXTURE_RECTANGLE);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, m_id);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE,0,0,0,0,0,m_width, m_height);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, 0);
|
||||
glDisable(GL_TEXTURE_RECTANGLE);
|
||||
}
|
||||
|
||||
// opengl buffer interface
|
||||
ClientBuffer::ClientBuffer(GLenum target = GL_ARRAY_BUFFER) {
|
||||
pglGenBuffers(1, &m_id);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ cdef class ShaderProgram:
|
|||
|
||||
def __repr__(self):
|
||||
return "()"
|
||||
|
||||
|
||||
cpdef bint isValid(self):
|
||||
'''
|
||||
Return status
|
||||
|
|
@ -94,4 +94,282 @@ cdef class ShaderProgram:
|
|||
ret = prog.build(vertex_src, fragment_src)
|
||||
|
||||
if not ret:
|
||||
raise GLError(errorMessage)
|
||||
raise GLError(errorMessage)
|
||||
|
||||
@classmethod
|
||||
def flat(cls):
|
||||
cdef ShaderProgram ret = ShaderProgram()
|
||||
ret.build(GLSL_VERTEX_FLAT, GLSL_FRAG_FLAT)
|
||||
return ret
|
||||
|
||||
@classmethod
|
||||
def pongDiffuse(cls, int lights):
|
||||
cdef ShaderProgram ret = ShaderProgram()
|
||||
|
||||
if lights < 1 or lights > 8:
|
||||
raise GLError('lights must be between 1 and 8')
|
||||
|
||||
INIT = "#define MAX_LIGHTS %d" % lights
|
||||
FRAG_SRC = "\n".join((INIT, GLSL_FRAG_PONG_COMMON, GLSL_FRAG_PONG_DIFFUSE))
|
||||
|
||||
ret.build(GLSL_VERTEX_PONG, FRAG_SRC)
|
||||
return ret
|
||||
|
||||
@classmethod
|
||||
def pongSpecular(cls, int lights):
|
||||
cdef ShaderProgram ret = ShaderProgram()
|
||||
|
||||
if lights < 1 or lights > 8:
|
||||
raise GLError('lights must be between 1 and 8')
|
||||
|
||||
INIT = "#define MAX_LIGHTS %d" % lights
|
||||
FRAG_SRC = "\n".join((INIT, GLSL_FRAG_PONG_COMMON, GLSL_FRAG_PONG_SPECULAR))
|
||||
|
||||
ret.build(GLSL_VERTEX_PONG, FRAG_SRC)
|
||||
return ret
|
||||
|
||||
# simple flat shader for overlay & background
|
||||
cdef char *GLSL_VERTEX_FLAT = \
|
||||
"""
|
||||
varying vec4 col;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
col = gl_Color;
|
||||
gl_Position = ftransform();
|
||||
}
|
||||
"""
|
||||
|
||||
cdef char *GLSL_FRAG_FLAT = \
|
||||
"""
|
||||
varying vec4 col;
|
||||
|
||||
void main (void)
|
||||
{
|
||||
gl_FragColor = col;
|
||||
}
|
||||
"""
|
||||
|
||||
# two sided per-pixel phong shader
|
||||
# ref: http://www.gamedev.net/page/resources/_/technical/opengl/creating-a-glsl-library-r2428
|
||||
|
||||
cdef char *GLSL_VERTEX_PONG = \
|
||||
"""
|
||||
varying vec3 normal;
|
||||
varying vec3 vertex;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Calculate the normal
|
||||
normal = normalize(gl_NormalMatrix * gl_Normal);
|
||||
|
||||
// Transform the vertex position to eye space
|
||||
vertex = vec3(gl_ModelViewMatrix * gl_Vertex);
|
||||
|
||||
gl_Position = ftransform();
|
||||
}
|
||||
"""
|
||||
|
||||
cdef char *GLSL_FRAG_PONG_COMMON = \
|
||||
"""
|
||||
varying vec3 normal;
|
||||
varying vec3 vertex;
|
||||
|
||||
float calculateAttenuation(in int i, in float dist)
|
||||
{
|
||||
return(1.0 / (gl_LightSource[i].constantAttenuation +
|
||||
gl_LightSource[i].linearAttenuation * dist +
|
||||
gl_LightSource[i].quadraticAttenuation * dist * dist));
|
||||
}
|
||||
|
||||
void directionalLight(in int i, in vec3 N, in float shininess,
|
||||
inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)
|
||||
{
|
||||
vec3 L = normalize(gl_LightSource[i].position.xyz);
|
||||
|
||||
float nDotL = dot(N, L);
|
||||
|
||||
if (nDotL > 0.0)
|
||||
{
|
||||
vec3 H = gl_LightSource[i].halfVector.xyz;
|
||||
|
||||
float pf = pow(max(dot(N,H), 0.0), shininess);
|
||||
|
||||
diffuse += gl_LightSource[i].diffuse * nDotL;
|
||||
specular += gl_LightSource[i].specular * pf;
|
||||
}
|
||||
|
||||
ambient += gl_LightSource[i].ambient;
|
||||
}
|
||||
|
||||
void pointLight(in int i, in vec3 N, in vec3 V, in float shininess,
|
||||
inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)
|
||||
{
|
||||
vec3 D = gl_LightSource[i].position.xyz - V;
|
||||
vec3 L = normalize(D);
|
||||
|
||||
float dist = length(D);
|
||||
float attenuation = calculateAttenuation(i, dist);
|
||||
|
||||
float nDotL = dot(N,L);
|
||||
|
||||
if (nDotL > 0.0)
|
||||
{
|
||||
vec3 E = normalize(-V);
|
||||
vec3 R = reflect(-L, N);
|
||||
|
||||
float pf = pow(max(dot(R,E), 0.0), shininess);
|
||||
|
||||
diffuse += gl_LightSource[i].diffuse * attenuation * nDotL;
|
||||
specular += gl_LightSource[i].specular * attenuation * pf;
|
||||
}
|
||||
|
||||
ambient += gl_LightSource[i].ambient * attenuation;
|
||||
}
|
||||
|
||||
void spotLight(in int i, in vec3 N, in vec3 V, in float shininess,
|
||||
inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)
|
||||
{
|
||||
vec3 D = gl_LightSource[i].position.xyz - V;
|
||||
vec3 L = normalize(D);
|
||||
|
||||
float dist = length(D);
|
||||
float attenuation = calculateAttenuation(i, dist);
|
||||
|
||||
float nDotL = dot(N,L);
|
||||
|
||||
if (nDotL > 0.0)
|
||||
{
|
||||
float spotEffect = dot(normalize(gl_LightSource[i].spotDirection), -L);
|
||||
|
||||
if (spotEffect > gl_LightSource[i].spotCosCutoff)
|
||||
{
|
||||
attenuation *= pow(spotEffect, gl_LightSource[i].spotExponent);
|
||||
|
||||
vec3 E = normalize(-V);
|
||||
vec3 R = reflect(-L, N);
|
||||
|
||||
float pf = pow(max(dot(R,E), 0.0), shininess);
|
||||
|
||||
diffuse += gl_LightSource[i].diffuse * attenuation * nDotL;
|
||||
specular += gl_LightSource[i].specular * attenuation * pf;
|
||||
}
|
||||
}
|
||||
|
||||
ambient += gl_LightSource[i].ambient * attenuation;
|
||||
}
|
||||
|
||||
void calculateLighting(in vec3 N, in vec3 V, in float shininess,
|
||||
inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)
|
||||
{
|
||||
// Just loop through each light, and add
|
||||
// its contributions to the color of the pixel.
|
||||
for (int i = 0; i < MAX_LIGHTS - 1; i++)
|
||||
{
|
||||
if (gl_LightSource[i].position.w == 0.0)
|
||||
directionalLight(i, N, shininess, ambient, diffuse, specular);
|
||||
else if (gl_LightSource[i].spotCutoff == 180.0)
|
||||
pointLight(i, N, V, shininess, ambient, diffuse, specular);
|
||||
else
|
||||
spotLight(i, N, V, shininess, ambient, diffuse, specular);
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
cdef char *GLSL_FRAG_PONG_SPECULAR = \
|
||||
"""
|
||||
void main()
|
||||
{
|
||||
// Normalize the normal. A varying variable CANNOT
|
||||
// be modified by a fragment shader. So a new variable
|
||||
// needs to be created.
|
||||
vec3 n = normalize(normal);
|
||||
|
||||
vec4 ambient, diffuse, specular, color;
|
||||
|
||||
// Initialize the contributions.
|
||||
ambient = vec4(0.0);
|
||||
diffuse = vec4(0.0);
|
||||
specular = vec4(0.0);
|
||||
|
||||
// In this case the built in uniform gl_MaxLights is used
|
||||
// to denote the number of lights. A better option may be passing
|
||||
// in the number of lights as a uniform or replacing the current
|
||||
// value with a smaller value.
|
||||
calculateLighting(n, vertex, gl_FrontMaterial.shininess,
|
||||
ambient, diffuse, specular);
|
||||
|
||||
color = gl_FrontLightModelProduct.sceneColor +
|
||||
(ambient * gl_FrontMaterial.ambient) +
|
||||
(diffuse * gl_FrontMaterial.diffuse) +
|
||||
(specular * gl_FrontMaterial.specular);
|
||||
|
||||
// Re-initialize the contributions for the back
|
||||
// pass over the lights
|
||||
ambient = vec4(0.0);
|
||||
diffuse = vec4(0.0);
|
||||
specular = vec4(0.0);
|
||||
|
||||
// Now caculate the back contribution. All that needs to be
|
||||
// done is to flip the normal.
|
||||
calculateLighting(-n, vertex, gl_BackMaterial.shininess,
|
||||
ambient, diffuse, specular);
|
||||
|
||||
color += gl_BackLightModelProduct.sceneColor +
|
||||
(ambient * gl_BackMaterial.ambient) +
|
||||
(diffuse * gl_BackMaterial.diffuse) +
|
||||
(specular * gl_BackMaterial.specular);
|
||||
|
||||
color = clamp(color, 0.0, 1.0);
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
"""
|
||||
|
||||
cdef char *GLSL_FRAG_PONG_DIFFUSE = \
|
||||
"""
|
||||
void main()
|
||||
{
|
||||
// Normalize the normal. A varying variable CANNOT
|
||||
// be modified by a fragment shader. So a new variable
|
||||
// needs to be created.
|
||||
vec3 n = normalize(normal);
|
||||
|
||||
vec4 ambient, diffuse, specular, color;
|
||||
|
||||
// Initialize the contributions.
|
||||
ambient = vec4(0.0);
|
||||
diffuse = vec4(0.0);
|
||||
specular = vec4(0.0);
|
||||
|
||||
// In this case the built in uniform gl_MaxLights is used
|
||||
// to denote the number of lights. A better option may be passing
|
||||
// in the number of lights as a uniform or replacing the current
|
||||
// value with a smaller value.
|
||||
calculateLighting(n, vertex, gl_FrontMaterial.shininess,
|
||||
ambient, diffuse, specular);
|
||||
|
||||
color = gl_FrontLightModelProduct.sceneColor +
|
||||
(ambient * gl_FrontMaterial.ambient) +
|
||||
(diffuse * gl_FrontMaterial.diffuse);
|
||||
|
||||
// Re-initialize the contributions for the back
|
||||
// pass over the lights
|
||||
ambient = vec4(0.0);
|
||||
diffuse = vec4(0.0);
|
||||
specular = vec4(0.0);
|
||||
|
||||
// Now caculate the back contribution. All that needs to be
|
||||
// done is to flip the normal.
|
||||
calculateLighting(-n, vertex, gl_BackMaterial.shininess,
|
||||
ambient, diffuse, specular);
|
||||
|
||||
color += gl_BackLightModelProduct.sceneColor +
|
||||
(ambient * gl_BackMaterial.ambient) +
|
||||
(diffuse * gl_BackMaterial.diffuse);
|
||||
|
||||
color = clamp(color, 0.0, 1.0);
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
"""
|
||||
|
|
|
|||
52
gltools/@src/Texture.pxi
Normal file
52
gltools/@src/Texture.pxi
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of gltools - See LICENSE.txt
|
||||
#
|
||||
|
||||
cdef class TextureRect2D:
|
||||
'''
|
||||
Abstraction of OpenGL 2d rectangular texture used
|
||||
for keeping a buffer of the screen content.
|
||||
'''
|
||||
def __init__(self, int width, int height, int depth = 3):
|
||||
self.thisptr = new c_TextureRect2D(width, height, depth, NULL)
|
||||
if not glCheck():
|
||||
raise GLError(errorMessage)
|
||||
|
||||
def __dealloc__(self):
|
||||
cdef c_TextureRect2D *tmp
|
||||
|
||||
if self.thisptr != NULL:
|
||||
tmp = <c_TextureRect2D *>self.thisptr
|
||||
del tmp
|
||||
|
||||
def __str__(self):
|
||||
return "TextureRect2D%s" % repr(self)
|
||||
|
||||
def __repr__(self):
|
||||
cdef c_TextureRect2D *tex = <c_TextureRect2D *>self.thisptr
|
||||
args = tex.m_width, tex.m_height, tex.m_depth
|
||||
return "(width = %d, height = %d, depth = %d)" % args
|
||||
|
||||
cpdef blit(self, float x = 0., float y = 0.):
|
||||
'''
|
||||
Blit content of the texture to the back buffer.
|
||||
'''
|
||||
cdef c_TextureRect2D *tex = <c_TextureRect2D *>self.thisptr
|
||||
tex.blit(x, y)
|
||||
|
||||
cpdef copy(self, int mode = GL_BACK):
|
||||
'''
|
||||
Copy buffer content to texture.
|
||||
'''
|
||||
cdef c_TextureRect2D *tex = <c_TextureRect2D *>self.thisptr
|
||||
tex.copy(mode)
|
||||
|
||||
@classmethod
|
||||
def fromImage(cls, Image img):
|
||||
'''
|
||||
Create texture from existing image
|
||||
'''
|
||||
cpdef TextureRect2D ret = TextureRect2D.__new__(TextureRect2D)
|
||||
ret.thisptr = new c_TextureRect2D(img.width, img.height, img.bytesPerPixel, img._buffer)
|
||||
return ret
|
||||
|
|
@ -23,6 +23,8 @@ cdef class Material:
|
|||
cdef readonly int mode
|
||||
cpdef enable(self)
|
||||
|
||||
cpdef ambientLight(ColorRGBA col)
|
||||
|
||||
cdef class Light:
|
||||
cdef public Material material
|
||||
cdef public Point position
|
||||
|
|
@ -31,6 +33,11 @@ cdef class Light:
|
|||
cdef readonly int index
|
||||
cpdef enable(self)
|
||||
cpdef disable(self)
|
||||
|
||||
cdef class TextureRect2D:
|
||||
cdef void *thisptr
|
||||
cpdef blit(self, float x = ?, float y = ?)
|
||||
cpdef copy(self, int mode = ?)
|
||||
|
||||
cdef class ClientBuffer:
|
||||
cdef void *thisptr
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ include "GL.pxi"
|
|||
include "ClientBuffer.pxi"
|
||||
include "ShaderProgram.pxi"
|
||||
include "Text.pxi"
|
||||
include "Texture.pxi"
|
||||
include "UI.pxi"
|
||||
|
||||
def test2d(double [:, ::1] arr):
|
||||
|
|
|
|||
187
gltools/test.py
187
gltools/test.py
|
|
@ -50,177 +50,6 @@ indices = array.array('B',(
|
|||
20,21,22, 22,23,20, # back
|
||||
))
|
||||
|
||||
GLSL_VERTEX = \
|
||||
"""
|
||||
varying vec3 normal;
|
||||
varying vec3 vertex;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Calculate the normal
|
||||
normal = normalize(gl_NormalMatrix * gl_Normal);
|
||||
|
||||
// Transform the vertex position to eye space
|
||||
vertex = vec3(gl_ModelViewMatrix * gl_Vertex);
|
||||
|
||||
gl_Position = ftransform();
|
||||
}
|
||||
"""
|
||||
|
||||
GLSL_FRAG = \
|
||||
"""
|
||||
#define MAX_LIGHTS 3
|
||||
varying vec3 normal;
|
||||
varying vec3 vertex;
|
||||
|
||||
float calculateAttenuation(in int i, in float dist)
|
||||
{
|
||||
return(1.0 / (gl_LightSource[i].constantAttenuation +
|
||||
gl_LightSource[i].linearAttenuation * dist +
|
||||
gl_LightSource[i].quadraticAttenuation * dist * dist));
|
||||
}
|
||||
|
||||
void directionalLight(in int i, in vec3 N, in float shininess,
|
||||
inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)
|
||||
{
|
||||
vec3 L = normalize(gl_LightSource[i].position.xyz);
|
||||
|
||||
float nDotL = dot(N, L);
|
||||
|
||||
if (nDotL > 0.0)
|
||||
{
|
||||
vec3 H = gl_LightSource[i].halfVector.xyz;
|
||||
|
||||
float pf = pow(max(dot(N,H), 0.0), shininess);
|
||||
|
||||
diffuse += gl_LightSource[i].diffuse * nDotL;
|
||||
specular += gl_LightSource[i].specular * pf;
|
||||
}
|
||||
|
||||
ambient += gl_LightSource[i].ambient;
|
||||
}
|
||||
|
||||
void pointLight(in int i, in vec3 N, in vec3 V, in float shininess,
|
||||
inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)
|
||||
{
|
||||
vec3 D = gl_LightSource[i].position.xyz - V;
|
||||
vec3 L = normalize(D);
|
||||
|
||||
float dist = length(D);
|
||||
float attenuation = calculateAttenuation(i, dist);
|
||||
|
||||
float nDotL = dot(N,L);
|
||||
|
||||
if (nDotL > 0.0)
|
||||
{
|
||||
vec3 E = normalize(-V);
|
||||
vec3 R = reflect(-L, N);
|
||||
|
||||
float pf = pow(max(dot(R,E), 0.0), shininess);
|
||||
|
||||
diffuse += gl_LightSource[i].diffuse * attenuation * nDotL;
|
||||
specular += gl_LightSource[i].specular * attenuation * pf;
|
||||
}
|
||||
|
||||
ambient += gl_LightSource[i].ambient * attenuation;
|
||||
}
|
||||
|
||||
void spotLight(in int i, in vec3 N, in vec3 V, in float shininess,
|
||||
inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)
|
||||
{
|
||||
vec3 D = gl_LightSource[i].position.xyz - V;
|
||||
vec3 L = normalize(D);
|
||||
|
||||
float dist = length(D);
|
||||
float attenuation = calculateAttenuation(i, dist);
|
||||
|
||||
float nDotL = dot(N,L);
|
||||
|
||||
if (nDotL > 0.0)
|
||||
{
|
||||
float spotEffect = dot(normalize(gl_LightSource[i].spotDirection), -L);
|
||||
|
||||
if (spotEffect > gl_LightSource[i].spotCosCutoff)
|
||||
{
|
||||
attenuation *= pow(spotEffect, gl_LightSource[i].spotExponent);
|
||||
|
||||
vec3 E = normalize(-V);
|
||||
vec3 R = reflect(-L, N);
|
||||
|
||||
float pf = pow(max(dot(R,E), 0.0), shininess);
|
||||
|
||||
diffuse += gl_LightSource[i].diffuse * attenuation * nDotL;
|
||||
specular += gl_LightSource[i].specular * attenuation * pf;
|
||||
}
|
||||
}
|
||||
|
||||
ambient += gl_LightSource[i].ambient * attenuation;
|
||||
}
|
||||
|
||||
void calculateLighting(in vec3 N, in vec3 V, in float shininess,
|
||||
inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)
|
||||
{
|
||||
// Just loop through each light, and add
|
||||
// its contributions to the color of the pixel.
|
||||
for (int i = 0; i < MAX_LIGHTS - 1; i++)
|
||||
{
|
||||
if (gl_LightSource[i].position.w == 0.0)
|
||||
directionalLight(i, N, shininess, ambient, diffuse, specular);
|
||||
else if (gl_LightSource[i].spotCutoff == 180.0)
|
||||
pointLight(i, N, V, shininess, ambient, diffuse, specular);
|
||||
else
|
||||
spotLight(i, N, V, shininess, ambient, diffuse, specular);
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// Normalize the normal. A varying variable CANNOT
|
||||
// be modified by a fragment shader. So a new variable
|
||||
// needs to be created.
|
||||
vec3 n = normalize(normal);
|
||||
|
||||
vec4 ambient, diffuse, specular, color;
|
||||
|
||||
// Initialize the contributions.
|
||||
ambient = vec4(0.0);
|
||||
diffuse = vec4(0.0);
|
||||
specular = vec4(0.0);
|
||||
|
||||
// In this case the built in uniform gl_MaxLights is used
|
||||
// to denote the number of lights. A better option may be passing
|
||||
// in the number of lights as a uniform or replacing the current
|
||||
// value with a smaller value.
|
||||
calculateLighting(n, vertex, gl_FrontMaterial.shininess,
|
||||
ambient, diffuse, specular);
|
||||
|
||||
color = gl_FrontLightModelProduct.sceneColor +
|
||||
(ambient * gl_FrontMaterial.ambient) +
|
||||
(diffuse * gl_FrontMaterial.diffuse) +
|
||||
(specular * gl_FrontMaterial.specular);
|
||||
|
||||
// Re-initialize the contributions for the back
|
||||
// pass over the lights
|
||||
ambient = vec4(0.0);
|
||||
diffuse = vec4(0.0);
|
||||
specular = vec4(0.0);
|
||||
|
||||
// Now caculate the back contribution. All that needs to be
|
||||
// done is to flip the normal.
|
||||
calculateLighting(-n, vertex, gl_BackMaterial.shininess,
|
||||
ambient, diffuse, specular);
|
||||
|
||||
color += gl_BackLightModelProduct.sceneColor +
|
||||
(ambient * gl_BackMaterial.ambient) +
|
||||
(diffuse * gl_BackMaterial.diffuse) +
|
||||
(specular * gl_BackMaterial.specular);
|
||||
|
||||
color = clamp(color, 0.0, 1.0);
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
"""
|
||||
|
||||
class MainWindow(gl.Window):
|
||||
def __init__(self, width, height, title):
|
||||
self.initialized = False
|
||||
|
|
@ -280,9 +109,8 @@ class MainWindow(gl.Window):
|
|||
)
|
||||
|
||||
# GLSL
|
||||
glsl = self.program = gl.ShaderProgram()
|
||||
glsl.build(GLSL_VERTEX, GLSL_FRAG)
|
||||
|
||||
glsl = self.program = gl.ShaderProgram.pongDiffuse(3)
|
||||
|
||||
# mesh
|
||||
fsize = vertices.itemsize
|
||||
buffer = self.buffer = gl.ClientBuffer()
|
||||
|
|
@ -433,20 +261,25 @@ class MainWindow(gl.Window):
|
|||
cam = self.cam
|
||||
|
||||
ui = self.insideUI(x, y)
|
||||
|
||||
|
||||
update = False
|
||||
if not ui and self.currentButton == gl.MOUSE.LEFT:
|
||||
# rotate view
|
||||
dx = x - lastx
|
||||
dy = y - lasty
|
||||
cam.rotateDeltas(dx, dy, target = self.mouseCenter)
|
||||
update = True
|
||||
|
||||
elif not ui and self.currentButton == gl.MOUSE.RIGHT:
|
||||
# pan view
|
||||
cam.pan(lastx, lasty, x, y, target = self.mouseCenter)
|
||||
|
||||
update = True
|
||||
|
||||
#print 'onCursorPos ', x, y
|
||||
self.lastPos = x, y
|
||||
self.onRefresh()
|
||||
|
||||
if ui or update:
|
||||
self.onRefresh()
|
||||
|
||||
def onMouseButton(self, button, action):
|
||||
#print 'onMouseButton ', button, action
|
||||
|
|
|
|||
Loading…
Reference in a new issue