350 lines
12 KiB
Cython
350 lines
12 KiB
Cython
#cython: profile=False
|
|
# Copyright 2004-2019 Tom Rothamel <pytom@bishoujo.us>
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person
|
|
# obtaining a copy of this software and associated documentation files
|
|
# (the "Software"), to deal in the Software without restriction,
|
|
# including without limitation the rights to use, copy, modify, merge,
|
|
# publish, distribute, sublicense, and/or sell copies of the Software,
|
|
# and to permit persons to whom the Software is furnished to do so,
|
|
# subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be
|
|
# included in all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
from __future__ import print_function
|
|
|
|
from gl1 cimport *
|
|
from gldraw cimport *
|
|
|
|
NONE = 0
|
|
BLIT = 1
|
|
BLEND = 2
|
|
IMAGEBLEND = 3
|
|
|
|
cdef void gl_clip(GLenum plane, GLdouble a, GLdouble b, GLdouble c, GLdouble d):
|
|
"""
|
|
Utility function that takes care of setting up an OpenGL clip plane.
|
|
"""
|
|
|
|
cdef GLdouble equation[4]
|
|
|
|
equation[0] = a
|
|
equation[1] = b
|
|
equation[2] = c
|
|
equation[3] = d
|
|
glEnable(plane)
|
|
glClipPlane(plane, equation)
|
|
|
|
cdef class FixedFunctionEnviron(Environ):
|
|
"""
|
|
This is an OpenGL environment that uses the fixed-function pipeline.
|
|
|
|
It requires ARB_texture_env_combine and ARB_texture_env_crossbar to
|
|
work.
|
|
"""
|
|
|
|
cdef object last
|
|
cdef int last_ramp
|
|
cdef int last_ramplen
|
|
cdef object ramp_setup
|
|
|
|
def init(self):
|
|
|
|
# The last blend environ used.
|
|
self.last = NONE
|
|
|
|
# The last ramp length asked for.
|
|
self.last_ramp = -1
|
|
|
|
# The last ramplen actually used.
|
|
self.last_ramplen = -1
|
|
|
|
# A table that maps ramp lengths to the setup of the fixed-function
|
|
# units.
|
|
self.ramp_setup = [
|
|
# Fields are:
|
|
# ramp length,
|
|
# unit 1 scale,
|
|
# unit 2 function,
|
|
# unit 2 scale,
|
|
|
|
(256, 1.0, GL_REPLACE, 1.0),
|
|
(128, 1.0, GL_REPLACE, 2.0),
|
|
(64, 1.0, GL_REPLACE, 4.0),
|
|
(32, 1.0, GL_ADD, 4.0),
|
|
(16, 2.0, GL_ADD, 4.0),
|
|
(8, 4.0, GL_ADD, 4.0),
|
|
]
|
|
|
|
|
|
def deinit(self):
|
|
"""
|
|
Called before changing the GL context.
|
|
"""
|
|
|
|
return
|
|
|
|
def disable(self, unit):
|
|
"""
|
|
Disables the given texture combiner.
|
|
"""
|
|
|
|
glActiveTextureARB(unit)
|
|
glDisable(GL_TEXTURE_2D)
|
|
|
|
# As this takes keyword arguments, it can't be a cdef function.
|
|
def combine_mode(self, unit,
|
|
color_function=GL_MODULATE,
|
|
color_arg0=GL_TEXTURE,
|
|
color_arg1=GL_PREVIOUS_ARB,
|
|
color_arg2=GL_CONSTANT_ARB,
|
|
color_source0=GL_SRC_COLOR,
|
|
color_source1=GL_SRC_COLOR,
|
|
color_source2=GL_SRC_COLOR,
|
|
color_scale=1.0,
|
|
alpha_function=GL_MODULATE,
|
|
alpha_arg0=GL_TEXTURE,
|
|
alpha_arg1=GL_PREVIOUS_ARB,
|
|
alpha_arg2=GL_CONSTANT_ARB,
|
|
alpha_source0=GL_SRC_ALPHA,
|
|
alpha_source1=GL_SRC_ALPHA,
|
|
alpha_source2=GL_SRC_ALPHA,
|
|
alpha_scale=1.0,
|
|
enable=True):
|
|
|
|
|
|
glActiveTextureARB(unit)
|
|
|
|
if enable:
|
|
glEnable(GL_TEXTURE_2D)
|
|
else:
|
|
glDisable(GL_TEXTURE_2D)
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB)
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, color_function)
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, alpha_function)
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, color_arg0)
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, color_source0)
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, color_arg1)
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, color_source1)
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, color_arg2)
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, color_source2)
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, alpha_arg0)
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, alpha_source0)
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, alpha_arg1)
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, alpha_source1)
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, alpha_arg2)
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, alpha_source2)
|
|
|
|
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, color_scale)
|
|
glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, alpha_scale)
|
|
|
|
|
|
cdef void blit(self):
|
|
|
|
if self.last != BLIT:
|
|
|
|
# Set unit 0 to modulate.
|
|
|
|
self.combine_mode(GL_TEXTURE0_ARB,
|
|
color_function=GL_MODULATE,
|
|
alpha_function=GL_MODULATE)
|
|
|
|
|
|
# Disable units 1, 2 and 3.
|
|
self.disable(GL_TEXTURE1_ARB)
|
|
self.disable(GL_TEXTURE2_ARB)
|
|
self.disable(GL_TEXTURE3_ARB)
|
|
|
|
self.last = BLIT
|
|
|
|
cdef void blend(self, double fraction):
|
|
|
|
if self.last != BLEND:
|
|
|
|
# Get texture 0.
|
|
self.combine_mode(GL_TEXTURE0_ARB,
|
|
color_function=GL_REPLACE,
|
|
alpha_function=GL_REPLACE)
|
|
|
|
# Use interpolate to combine texture 0 with texture 1, as
|
|
# controlled by the constant of texture unit 1.
|
|
self.combine_mode(GL_TEXTURE1_ARB,
|
|
color_function=GL_INTERPOLATE_ARB,
|
|
color_arg0=GL_TEXTURE1_ARB,
|
|
color_arg1=GL_TEXTURE0_ARB,
|
|
alpha_function=GL_INTERPOLATE_ARB,
|
|
alpha_arg0=GL_TEXTURE1_ARB,
|
|
alpha_arg1=GL_TEXTURE0_ARB)
|
|
|
|
# Combine the interpolated result with the primary color, to
|
|
# allow for tinting and alpha adjustments.
|
|
self.combine_mode(GL_TEXTURE2_ARB,
|
|
color_function=GL_MODULATE,
|
|
color_arg0=GL_PREVIOUS_ARB,
|
|
color_arg1=GL_PRIMARY_COLOR_ARB,
|
|
alpha_function=GL_MODULATE,
|
|
alpha_arg0=GL_PREVIOUS_ARB,
|
|
alpha_arg1=GL_PRIMARY_COLOR_ARB,
|
|
enable=False)
|
|
|
|
# Disable texture unit 3.
|
|
self.disable(GL_TEXTURE3_ARB)
|
|
|
|
self.last = BLEND
|
|
|
|
cdef float *fractions = [ fraction, fraction, fraction, fraction ]
|
|
|
|
glActiveTextureARB(GL_TEXTURE1_ARB)
|
|
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, fractions)
|
|
|
|
|
|
|
|
cdef void imageblend(self, double fraction, int ramp):
|
|
|
|
if self.last != IMAGEBLEND or self.last_ramp != ramp:
|
|
|
|
# Figure out the details of the ramp.
|
|
for i in self.ramp_setup:
|
|
ramplen, t0scale, t1function, t1scale = i
|
|
|
|
# We round the ramplen down, unless we're below the
|
|
# smallest size, in which case we increase it.
|
|
if ramplen <= ramp:
|
|
break
|
|
|
|
# Unit 0 loads in the control image, and adds/subtracts an
|
|
# offset to/from it. (We'll set it up to subtract here,
|
|
# and change this later on as necessary.)
|
|
#
|
|
# It multiplies this result by up to 4.
|
|
self.combine_mode(GL_TEXTURE0_ARB,
|
|
color_function=GL_SUBTRACT_ARB,
|
|
alpha_function=GL_SUBTRACT_ARB,
|
|
color_arg1=GL_CONSTANT_ARB,
|
|
alpha_arg1=GL_CONSTANT_ARB,
|
|
color_scale=t0scale,
|
|
alpha_scale=t0scale)
|
|
|
|
# Unit 1 will multiply the result of stage 1 by up to 8.
|
|
#
|
|
# It also takes the first source texture, but we don't
|
|
# access it directly yet.
|
|
self.combine_mode(GL_TEXTURE1_ARB,
|
|
color_function=t1function,
|
|
alpha_function=t1function,
|
|
color_arg0=GL_PREVIOUS_ARB,
|
|
color_arg1=GL_PREVIOUS_ARB,
|
|
alpha_arg0=GL_PREVIOUS_ARB,
|
|
alpha_arg1=GL_PREVIOUS_ARB,
|
|
color_scale=t1scale,
|
|
alpha_scale=t1scale)
|
|
|
|
# Unit 2 uses the result of unit 1 to interpolate between the
|
|
# unit 1 and unit 2 textures.
|
|
self.combine_mode(GL_TEXTURE2_ARB,
|
|
color_function=GL_INTERPOLATE_ARB,
|
|
alpha_function=GL_INTERPOLATE_ARB,
|
|
color_arg0=GL_TEXTURE2_ARB,
|
|
color_arg1=GL_TEXTURE1_ARB,
|
|
color_arg2=GL_PREVIOUS_ARB,
|
|
alpha_arg0=GL_TEXTURE2_ARB,
|
|
alpha_arg1=GL_TEXTURE1_ARB,
|
|
alpha_arg2=GL_PREVIOUS_ARB)
|
|
|
|
# Finally, Unit 3 modulates the result of unit 2 with the color.
|
|
self.combine_mode(GL_TEXTURE3_ARB,
|
|
color_function=GL_MODULATE,
|
|
color_arg0=GL_PREVIOUS_ARB,
|
|
color_arg1=GL_PRIMARY_COLOR_ARB,
|
|
alpha_function=GL_MODULATE,
|
|
alpha_arg0=GL_PREVIOUS_ARB,
|
|
alpha_arg1=GL_PRIMARY_COLOR_ARB,
|
|
enable=False)
|
|
|
|
self.last = IMAGEBLEND
|
|
self.last_ramp = ramp
|
|
self.last_ramplen = ramplen
|
|
|
|
# Compute the offset to apply to the alpha.
|
|
start = -1.0
|
|
end = self.last_ramplen / 256.0
|
|
offset = start + ( end - start) * fraction
|
|
|
|
# Decide if we're adding or subtracting.
|
|
if offset < 0:
|
|
function = GL_SUBTRACT_ARB
|
|
offset = -offset
|
|
else:
|
|
function = GL_ADD
|
|
|
|
# Setup unit 0 as appropriate.
|
|
glActiveTextureARB(GL_TEXTURE0_ARB)
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, function)
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, function)
|
|
|
|
cdef float *offsets = [ offset, offset, offset, offset ]
|
|
|
|
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, offsets)
|
|
|
|
cdef void set_vertex(self, float *vertices):
|
|
glVertexPointer(2, GL_FLOAT, 0, <GLubyte *> vertices)
|
|
glEnableClientState(GL_VERTEX_ARRAY)
|
|
|
|
cdef void set_texture(self, int unit, float *coords):
|
|
|
|
if unit == 0:
|
|
glClientActiveTextureARB(GL_TEXTURE0)
|
|
elif unit == 1:
|
|
glClientActiveTextureARB(GL_TEXTURE1)
|
|
elif RENPY_THIRD_TEXTURE and unit == 2:
|
|
glClientActiveTextureARB(GL_TEXTURE2)
|
|
else:
|
|
return
|
|
|
|
if coords is not NULL:
|
|
glTexCoordPointer(2, GL_FLOAT, 0, <GLubyte *> coords)
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
|
|
else:
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY)
|
|
|
|
cdef void set_color(self, double r, double g, double b, double a):
|
|
glColor4f(r, g, b, a)
|
|
|
|
cdef void ortho(self, double left, double right, double bottom, double top, double near, double far):
|
|
|
|
glMatrixMode(GL_PROJECTION)
|
|
glLoadIdentity()
|
|
glOrtho(left, right, bottom, top, near, far)
|
|
glMatrixMode(GL_MODELVIEW)
|
|
|
|
cdef void set_clip(self, tuple clip_box, GLDraw draw):
|
|
|
|
cdef double minx, miny, maxx, maxy
|
|
|
|
minx, miny, maxx, maxy = clip_box
|
|
|
|
gl_clip(GL_CLIP_PLANE0, 1.0, 0.0, 0.0, -minx - .01)
|
|
gl_clip(GL_CLIP_PLANE1, 0.0, 1.0, 0.0, -miny - .01)
|
|
gl_clip(GL_CLIP_PLANE2, -1.0, 0.0, 0.0, maxx + .01)
|
|
gl_clip(GL_CLIP_PLANE3, 0.0, -1.0, 0.0, maxy + .01)
|
|
|
|
cdef void unset_clip(self, GLDraw draw):
|
|
glDisable(GL_CLIP_PLANE0)
|
|
glDisable(GL_CLIP_PLANE1)
|
|
glDisable(GL_CLIP_PLANE2)
|
|
glDisable(GL_CLIP_PLANE3)
|
|
|
|
cdef void viewport(self, int x, int y, int width, int height):
|
|
glViewport(x, y, width, height)
|