Skip to content

Commit

Permalink
Add skybox and cubemap reflections (fresnel). Switch gletools for pyg…
Browse files Browse the repository at this point in the history
…let-shaders
  • Loading branch information
pabennett committed Apr 23, 2013
1 parent 9e3ab74 commit 51f2437
Show file tree
Hide file tree
Showing 18 changed files with 489 additions and 37 deletions.
5 changes: 4 additions & 1 deletion README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ This code has been written in Python 2.7 with the following additional modules:

[Pyglet](http://www.pyglet.org/ "Pyglet") for OpenGL and windowing + controls

[Gletools](http://codeflow.org/entries/2009/jul/31/gletools-advanced-pyglet-utilities/ "Gletools") to allow compilation of GLSL shaders
Code from the
[pyglet-shaders](https://code.google.com/p/pyglet-shaders/ "pyglet-shaders")
project is used for compiling GLSL shaders.

Features
--------
Expand Down Expand Up @@ -108,3 +110,4 @@ Thanks to Keith Lantz for his [excellent guide](http://www.keithlantz.net/2011/1
on Tessendorf's ocean simulation technique

The sand and tile textures are by Patrick Hoesly on [Flickr](http://www.flickr.com/photos/zooboing/ "Zooboing")
The sky environment map "Miramar" is by Jockum "hipshot" Skoglund: [www.zfight.com](http://www.zfight.com "www.zfight.com")
10 changes: 10 additions & 0 deletions images/environments/miramar/CREDITS.TXT
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
MIRAMAR
high res 1024^2 environment map
ships as TGA.

By Jockum Skoglund aka hipshot
hipshot@zfight.com
www.zfight.com
Stockholm, 2005 08 25

Modify however you like, just cred me for my work, maybe link to my page.
Binary file added images/environments/miramar/xneg.tga
Binary file not shown.
Binary file added images/environments/miramar/xpos.tga
Binary file not shown.
Binary file added images/environments/miramar/yneg.tga
Binary file not shown.
Binary file added images/environments/miramar/ypos.tga
Binary file not shown.
Binary file added images/environments/miramar/zneg.tga
Binary file not shown.
Binary file added images/environments/miramar/zpos.tga
Binary file not shown.
7 changes: 1 addition & 6 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@
from pyglet import *
from pyglet.gl import *
from pyglet.window import key
# gletools ShaderProgram is required to compile GLSL shaders, this can
# be replaced with a standalone shader class if preferred
# For example:
# http://swiftcoder.wordpress.com/2008/12/19/simple-glsl-wrapper-for-pyglet/
from gletools import ShaderProgram
from math import *
# Renderers:
from source import scene,camera,console
Expand Down Expand Up @@ -65,7 +60,7 @@
status.addParameter('Position')
status.addParameter('Velocity')

camera = camera.Camera(kScreenWidth, kScreenHeight, kVFOV, 0.1, 1000.)
camera = camera.Camera(kScreenWidth, kScreenHeight, kVFOV, 0.1, 3000.)

# Offset and orient the camera so that it is looking at the water.
camera.setpos(100.0, 140.0, 150.0)
Expand Down
5 changes: 3 additions & 2 deletions options.ini
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
[Options]
mousefocus=True
framegrabpath=F:/temp
screenwidth=1024
screenwidth=864
screenheight=864
fullscreen=False
fixedtimestep=False
timestep=0.1
maxFPS=120
buffers=2
samples=4
info=False
info=True
vfov=65
[Scene]
oceandepth = 55.0
Expand All @@ -22,3 +22,4 @@ oceantilesy = 5
causticintensity = 2.0
causticscale = 2
period = 20.0
env_path = images/environments/miramar
8 changes: 4 additions & 4 deletions source/caustics.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
from pyglet import *
from pyglet.gl import *
from gletools import ShaderProgram


from vector import Vector2, Vector3
from matrix16 import Matrix16

from utilities import frameBuffer, Pointfield2D, Mesh2DSurface

import numpy as np

import ctypes

import random
import shader

class Caustics():
def __init__(self,
Expand All @@ -31,7 +30,8 @@ def __init__(self,
self.tileSize = self.surface.tileSize

# Compile the shader
self.shader = ShaderProgram.open('shaders/photonMap.shader')
self.shader = shader.openfiles( 'shaders/photonmap.vertex',
'shaders/photonmap.fragment')

self.causticTexture = causticTexture

Expand Down
19 changes: 13 additions & 6 deletions source/heightfields.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
__author__ = "Peter Bennett"
__copyright__ = "Copyright 2013, Peter A Bennett"
__license__ = "LGPL"
__maintainer__ = "Peter Bennett"
__email__ = "pab850@gmail.com"
__contact__ = "www.bytebash.com"

from utilities import *

from math import *
import numpy as np
from vector import Vector2, Vector3

from ctypes import pointer, sizeof
from gletools import ShaderProgram

class Tessendorf():
def __init__(self,
Expand Down Expand Up @@ -291,11 +297,12 @@ def __init__(self, camera, dimension=64):

self.tapPosition = Vector2(0.0,0.0)


self.rippleShader = ShaderProgram.open('shaders/ripples.shader')
self.copyShader = ShaderProgram.open('shaders/passthru.shader')


self.rippleShader = shader.openfiles( 'shaders/ripples.vertex',
'shaders/ripples.fragment')

self.copyShader = shader.openfiles( 'shaders/passthru.vertex',
'shaders/passthru.fragment')

self.textureA = image.DepthTexture.create_for_size(GL_TEXTURE_2D,
self.N,
self.N,
Expand Down
34 changes: 30 additions & 4 deletions source/scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
import console
import ctypes
from vector import Vector2, Vector3

from water import Ocean, Pool
from skybox import Skybox
import shader

class Scene():
def __init__(self, window, camera, statusConsole, options):
Expand Down Expand Up @@ -69,11 +70,35 @@ def __init__(self, window, camera, statusConsole, options):
self.causticIntensity= self.options.getfloat('Scene','causticintensity')
self.causticPhotonScale = self.options.getfloat('Scene', 'causticscale')
self.period = self.options.getfloat('Scene', 'period')
self.env_path = self.options.get('Scene', 'env_path')
self.frame = 0
self.skyboxScale = 640.0
self.skyboxOffset = Vector3(0.0,0.0,0.0)

# Compile the shader
self.skyboxShader = shader.openfiles( 'shaders/skybox.vertex',
'shaders/skybox.fragment')


# Renderables
self.scene = []

self.skybox = Skybox(
self.skyboxShader,
self.camera,
self.skyboxScale,
self.skyboxOffset,
xpos_path=self.env_path + '/xpos.tga',
ypos_path=self.env_path + '/ypos.tga',
zpos_path=self.env_path + '/zpos.tga',
xneg_path=self.env_path + '/xneg.tga',
yneg_path=self.env_path + '/yneg.tga',
zneg_path=self.env_path + '/zneg.tga',
)
self.scene.append(self.skybox)

self.ocean = Ocean( self.camera,
cubemap=self.skybox,
depth=self.oceanDepth,
waveHeight=self.oceanWaveHeight,
wind=self.oceanWind,
Expand All @@ -83,9 +108,10 @@ def __init__(self, window, camera, statusConsole, options):
photonScale=self.causticPhotonScale,
photonIntensity=self.causticIntensity,
period=self.period)
self.scene.append(self.ocean)

self.scene.append(self.ocean)


def statusUpdates(self, dt):
'''
Called periodically by main loop for onscreen text updates
Expand All @@ -103,7 +129,7 @@ def draw(self, dt):
if self.isKeyPressed(key.C):
self.oceanDepth += 1
self.ocean.setDepth(self.oceanDepth)
elif self.isKeyPressed(key.V):
elif self.isKeyPressed(key.V) and self.oceanDepth > 0:
self.oceanDepth -= 1
self.ocean.setDepth(self.oceanDepth)

Expand Down
171 changes: 171 additions & 0 deletions source/shader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
'''
shader.py taken from https://code.google.com/p/pyglet-shaders/
'''
from ctypes import (
byref, c_char, c_char_p, c_int, cast, create_string_buffer, pointer,
POINTER
)
from pyglet import gl


class ShaderError(Exception): pass
class CompileError(ShaderError): pass
class LinkError(ShaderError): pass


shaderErrors = {
gl.GL_INVALID_VALUE: 'GL_INVALID_VALUE (bad 1st arg)',
gl.GL_INVALID_OPERATION: 'GL_INVALID_OPERATION '
'(bad id or immediate mode drawing in progress)',
gl.GL_INVALID_ENUM: 'GL_INVALID_ENUM (bad 2nd arg)',
}

def read_source(fname):
f = open(fname)
try:
src = f.read()
finally:
f.close()
return src


def openfiles(vertex, fragment):
fsrc = read_source(fragment)
fshader = FragmentShader([fsrc])
vsrc = read_source(vertex)
vshader = VertexShader([vsrc])

program = ShaderProgram(fshader, vshader)
program.use()
return program


class _Shader(object):

type = None

def __init__(self, sources):
if isinstance(sources, basestring):
self.sources = [sources]
else:
self.sources = sources
self.id = None


def _get(self, paramId):
outvalue = c_int(0)
gl.glGetShaderiv(self.id, paramId, byref(outvalue))
value = outvalue.value
if value in shaderErrors.keys():
msg = '%s from glGetShader(%s, %s, &value)'
raise ValueError(msg % (shaderErrors[value], self.id, paramId))
return value


def getCompileStatus(self):
return bool(self._get(gl.GL_COMPILE_STATUS))


def getInfoLogLength(self):
return self._get(gl.GL_INFO_LOG_LENGTH)


def getInfoLog(self):
length = self.getInfoLogLength()
if length == 0:
return ''
buffer = create_string_buffer(length)
gl.glGetShaderInfoLog(self.id, length, None, buffer)
return buffer.value


def _srcToArray(self):
num = len(self.sources)
all_source = (c_char_p * num)(*self.sources)
return num, cast(pointer(all_source), POINTER(POINTER(c_char)))


def compile(self):
self.id = gl.glCreateShader(self.type)

num, src = self._srcToArray()
gl.glShaderSource(self.id, num, src, None)

gl.glCompileShader(self.id)

if not self.getCompileStatus():
raise CompileError(self.getInfoLog())



class VertexShader(_Shader):
type = gl.GL_VERTEX_SHADER


class FragmentShader(_Shader):
type = gl.GL_FRAGMENT_SHADER



class ShaderProgram(object):

def __init__(self, *shaders):
self.shaders = list(shaders)
self.id = None


def _get(self, paramId):
outvalue = c_int(0)
gl.glGetProgramiv(self.id, paramId, byref(outvalue))
value = outvalue.value
if value in shaderErrors.keys():
msg = '%s from glGetProgram(%s, %s, &value)'
raise ValueError(msg % (shaderErrors[value], self.id, paramId))
return value


def getLinkStatus(self):
return bool(self._get(gl.GL_LINK_STATUS))


def getInfoLogLength(self):
return self._get(gl.GL_INFO_LOG_LENGTH)


def getInfoLog(self):
length = self.getInfoLogLength()
if length == 0:
return ''
buffer = create_string_buffer(length)
gl.glGetProgramInfoLog(self.id, length, None, buffer)
return buffer.value


def _getMessage(self):
messages = []
for shader in self.shaders:
log = shader.getInfoLog()
if log:
messages.append(log)
log = self.getInfoLog()
if log:
messages.append(log)
return '\n'.join(messages)


def use(self):
self.id = gl.glCreateProgram()

for shader in self.shaders:
shader.compile()
gl.glAttachShader(self.id, shader.id)

gl.glLinkProgram(self.id)

message = self._getMessage()
if not self.getLinkStatus():
raise LinkError(message)

gl.glUseProgram(self.id)
return message

Loading

0 comments on commit 51f2437

Please sign in to comment.