mirror of
https://github.com/quantum5/punyverse.git
synced 2025-04-24 13:11:57 -04:00
Switch clouds to shaders.
This commit is contained in:
parent
3770ec617b
commit
f7797949d9
|
@ -5,7 +5,7 @@ from pyglet.gl import *
|
||||||
# noinspection PyUnresolvedReferences
|
# noinspection PyUnresolvedReferences
|
||||||
from six.moves import range
|
from six.moves import range
|
||||||
|
|
||||||
from punyverse.glgeom import compile, glRestore, belt, Sphere, Disk, OrbitVBO, Matrix4f, SimpleSphere, TangentSphere
|
from punyverse.glgeom import compile, glRestore, belt, Disk, OrbitVBO, Matrix4f, SimpleSphere, TangentSphere
|
||||||
from punyverse.model import load_model, WavefrontVBO
|
from punyverse.model import load_model, WavefrontVBO
|
||||||
from punyverse.orbit import KeplerOrbit
|
from punyverse.orbit import KeplerOrbit
|
||||||
from punyverse.texture import get_best_texture, load_clouds
|
from punyverse.texture import get_best_texture, load_clouds
|
||||||
|
@ -32,9 +32,14 @@ class Entity(object):
|
||||||
def mv_matrix(self):
|
def mv_matrix(self):
|
||||||
return self.world.view_matrix() * self.model_matrix
|
return self.world.view_matrix() * self.model_matrix
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def mvp_matrix(self):
|
||||||
|
return self.world.vp_matrix * self.model_matrix
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
self.model_matrix = None
|
self.model_matrix = None
|
||||||
self.mv_matrix = None
|
self.mv_matrix = None
|
||||||
|
self.mvp_matrix = None
|
||||||
x, y, z = self.location
|
x, y, z = self.location
|
||||||
dx, dy, dz = self.direction
|
dx, dy, dz = self.direction
|
||||||
self.location = x + dx, y + dy, z + dz
|
self.location = x + dx, y + dy, z + dz
|
||||||
|
@ -316,8 +321,9 @@ class SphericalBody(Body):
|
||||||
atm_texture = atmosphere_data.get('diffuse_texture', None)
|
atm_texture = atmosphere_data.get('diffuse_texture', None)
|
||||||
cloud_texture = atmosphere_data.get('cloud_texture', None)
|
cloud_texture = atmosphere_data.get('cloud_texture', None)
|
||||||
if cloud_texture is not None:
|
if cloud_texture is not None:
|
||||||
self.cloud_texture = get_best_texture(cloud_texture, loader=load_clouds)
|
self.cloud_transparency = get_best_texture(cloud_texture, loader=load_clouds)
|
||||||
self.clouds = Sphere(self.radius + 2, division, division)
|
self.cloud_radius = self.radius + 2
|
||||||
|
self.clouds = self._get_sphere(division, tangent=False)
|
||||||
|
|
||||||
if atm_texture is not None:
|
if atm_texture is not None:
|
||||||
self.atm_texture = get_best_texture(atm_texture, clamp=True)
|
self.atm_texture = get_best_texture(atm_texture, clamp=True)
|
||||||
|
@ -341,7 +347,7 @@ class SphericalBody(Body):
|
||||||
shader.uniform_float('u_radius', self.radius)
|
shader.uniform_float('u_radius', self.radius)
|
||||||
shader.uniform_mat4('u_modelMatrix', self.model_matrix)
|
shader.uniform_mat4('u_modelMatrix', self.model_matrix)
|
||||||
shader.uniform_mat4('u_mvMatrix', self.mv_matrix)
|
shader.uniform_mat4('u_mvMatrix', self.mv_matrix)
|
||||||
shader.uniform_mat4('u_mvpMatrix', self.world.vp_matrix * self.model_matrix)
|
shader.uniform_mat4('u_mvpMatrix', self.mvp_matrix)
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0)
|
glActiveTexture(GL_TEXTURE0)
|
||||||
glBindTexture(GL_TEXTURE_2D, self.texture)
|
glBindTexture(GL_TEXTURE_2D, self.texture)
|
||||||
|
@ -395,7 +401,7 @@ class SphericalBody(Body):
|
||||||
def _draw_star(self):
|
def _draw_star(self):
|
||||||
shader = self.world.activate_shader('star')
|
shader = self.world.activate_shader('star')
|
||||||
shader.uniform_float('u_radius', self.radius)
|
shader.uniform_float('u_radius', self.radius)
|
||||||
shader.uniform_mat4('u_mvpMatrix', self.world.vp_matrix * self.model_matrix)
|
shader.uniform_mat4('u_mvpMatrix', self.mvp_matrix)
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0)
|
glActiveTexture(GL_TEXTURE0)
|
||||||
glBindTexture(GL_TEXTURE_2D, self.texture)
|
glBindTexture(GL_TEXTURE_2D, self.texture)
|
||||||
|
@ -436,17 +442,30 @@ class SphericalBody(Body):
|
||||||
self.atmosphere.draw()
|
self.atmosphere.draw()
|
||||||
|
|
||||||
def _draw_clouds(self):
|
def _draw_clouds(self):
|
||||||
with glRestore(GL_ENABLE_BIT | GL_TEXTURE_BIT):
|
|
||||||
glLoadMatrixf(self.mv_matrix)
|
|
||||||
glEnable(GL_BLEND)
|
glEnable(GL_BLEND)
|
||||||
glEnable(GL_ALPHA_TEST)
|
shader = self.world.activate_shader('clouds')
|
||||||
glEnable(GL_CULL_FACE)
|
shader.uniform_float('u_radius', self.cloud_radius)
|
||||||
glDisable(GL_LIGHTING)
|
shader.uniform_mat4('u_modelMatrix', self.model_matrix)
|
||||||
glEnable(GL_TEXTURE_2D)
|
shader.uniform_mat4('u_mvpMatrix', self.mvp_matrix)
|
||||||
|
|
||||||
glCullFace(GL_BACK)
|
glActiveTexture(GL_TEXTURE0)
|
||||||
glBindTexture(GL_TEXTURE_2D, self.cloud_texture)
|
glBindTexture(GL_TEXTURE_2D, self.cloud_transparency)
|
||||||
self.clouds.draw()
|
shader.uniform_texture('u_transparency', 0)
|
||||||
|
shader.uniform_vec3('u_diffuse', 1, 1, 1)
|
||||||
|
shader.uniform_vec3('u_ambient', 0.1, 0.1, 0.1)
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, self.clouds.vbo)
|
||||||
|
shader.vertex_attribute('a_normal', self.clouds.direction_size, self.clouds.type, GL_FALSE,
|
||||||
|
self.clouds.stride, self.clouds.direction_offset)
|
||||||
|
shader.vertex_attribute('a_uv', self.clouds.uv_size, self.clouds.type, GL_FALSE,
|
||||||
|
self.clouds.stride, self.clouds.uv_offset)
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.clouds.vertex_count)
|
||||||
|
|
||||||
|
shader.deactivate_attributes()
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
|
self.world.activate_shader(None)
|
||||||
|
glDisable(GL_BLEND)
|
||||||
|
|
||||||
def _draw_rings(self):
|
def _draw_rings(self):
|
||||||
with glRestore(GL_ENABLE_BIT | GL_TEXTURE_BIT):
|
with glRestore(GL_ENABLE_BIT | GL_TEXTURE_BIT):
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
from ctypes import pointer, byref, create_string_buffer, POINTER, cast
|
from ctypes import pointer, byref, create_string_buffer, POINTER, cast
|
||||||
|
|
||||||
from pyglet.gl import *
|
from pyglet.gl import *
|
||||||
|
@ -39,11 +40,15 @@ class Program(object):
|
||||||
succeeded = GLint()
|
succeeded = GLint()
|
||||||
log_length = GLint()
|
log_length = GLint()
|
||||||
glGetShaderiv(shader, GL_COMPILE_STATUS, byref(succeeded))
|
glGetShaderiv(shader, GL_COMPILE_STATUS, byref(succeeded))
|
||||||
if not succeeded:
|
|
||||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, byref(log_length))
|
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, byref(log_length))
|
||||||
buffer = create_string_buffer(log_length.value + 1)
|
buffer = create_string_buffer(log_length.value + 1)
|
||||||
glGetShaderInfoLog(shader, log_length.value, None, buffer)
|
glGetShaderInfoLog(shader, log_length.value, None, buffer)
|
||||||
raise CompileError(buffer.value)
|
|
||||||
|
if not succeeded:
|
||||||
|
raise CompileError(buffer.value.decode('utf-8'))
|
||||||
|
elif log_length.value:
|
||||||
|
print('Warning:', file=sys.stderr)
|
||||||
|
print(buffer.value.decode('utf-8'), file=sys.stderr)
|
||||||
|
|
||||||
def __init__(self, vertex_file, fragment_file):
|
def __init__(self, vertex_file, fragment_file):
|
||||||
with glShader(GL_VERTEX_SHADER) as vertex_shader, glShader(GL_FRAGMENT_SHADER) as fragment_shader:
|
with glShader(GL_VERTEX_SHADER) as vertex_shader, glShader(GL_FRAGMENT_SHADER) as fragment_shader:
|
||||||
|
|
19
punyverse/shaders/clouds.fragment.glsl
Normal file
19
punyverse/shaders/clouds.fragment.glsl
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#version 130
|
||||||
|
|
||||||
|
in vec2 v_uv;
|
||||||
|
in vec3 v_normal;
|
||||||
|
in vec3 v_position;
|
||||||
|
|
||||||
|
out vec4 o_fragColor;
|
||||||
|
|
||||||
|
uniform vec3 u_ambient;
|
||||||
|
uniform vec3 u_diffuse;
|
||||||
|
uniform vec3 u_sun;
|
||||||
|
uniform sampler2D u_transparency;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec3 incident = normalize(u_sun - v_position);
|
||||||
|
vec3 diffuse = u_diffuse * clamp(dot(v_normal, incident) + 0.2, 0.0, 1.0);
|
||||||
|
|
||||||
|
o_fragColor = vec4(u_ambient + diffuse, texture(u_transparency, v_uv).r);
|
||||||
|
}
|
20
punyverse/shaders/clouds.vertex.glsl
Normal file
20
punyverse/shaders/clouds.vertex.glsl
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#version 130
|
||||||
|
|
||||||
|
in vec3 a_normal;
|
||||||
|
in vec2 a_uv;
|
||||||
|
|
||||||
|
out vec2 v_uv;
|
||||||
|
out vec3 v_normal;
|
||||||
|
out vec3 v_position;
|
||||||
|
|
||||||
|
uniform float u_radius;
|
||||||
|
uniform mat4 u_mvpMatrix;
|
||||||
|
uniform mat4 u_modelMatrix;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec3 position = u_radius * a_normal;
|
||||||
|
v_uv = a_uv;
|
||||||
|
v_normal = (u_modelMatrix * vec4(a_normal, 0)).xyz;
|
||||||
|
v_position = (u_modelMatrix * vec4(position, 1)).xyz;
|
||||||
|
gl_Position = u_mvpMatrix * vec4(position, 1);
|
||||||
|
}
|
|
@ -6,6 +6,8 @@ in vec3 v_position;
|
||||||
in vec3 v_camDirection;
|
in vec3 v_camDirection;
|
||||||
in mat3 v_TBN;
|
in mat3 v_TBN;
|
||||||
|
|
||||||
|
out vec4 o_fragColor;
|
||||||
|
|
||||||
struct Surface {
|
struct Surface {
|
||||||
sampler2D diffuseMap;
|
sampler2D diffuseMap;
|
||||||
bool hasNormal;
|
bool hasNormal;
|
||||||
|
@ -49,5 +51,5 @@ void main() {
|
||||||
emission *= u_planet.emission * (1 - min(diffuseIntensity * 2, 1));
|
emission *= u_planet.emission * (1 - min(diffuseIntensity * 2, 1));
|
||||||
specular *= u_planet.specular * u_sun.specular * max(shininess, 0) * diffuseIntensity;
|
specular *= u_planet.specular * u_sun.specular * max(shininess, 0) * diffuseIntensity;
|
||||||
|
|
||||||
gl_FragColor = vec4((ambient + diffuse + emission + specular) * u_sun.intensity, 1);
|
o_fragColor = vec4((ambient + diffuse + emission + specular) * u_sun.intensity, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#version 130
|
#version 130
|
||||||
|
|
||||||
in vec2 v_uv;
|
in vec2 v_uv;
|
||||||
|
out vec4 o_fragColor;
|
||||||
uniform sampler2D u_skysphere;
|
uniform sampler2D u_skysphere;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_FragColor = vec4(texture(u_skysphere, v_uv).rgb, 1);
|
o_fragColor = vec4(texture(u_skysphere, v_uv).rgb, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#version 130
|
#version 130
|
||||||
|
|
||||||
in vec2 v_uv;
|
in vec2 v_uv;
|
||||||
|
out vec4 o_fragColor;
|
||||||
uniform sampler2D u_emission;
|
uniform sampler2D u_emission;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_FragColor = vec4(texture(u_emission, v_uv).rgb, 1);
|
o_fragColor = vec4(texture(u_emission, v_uv).rgb, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import itertools
|
|
||||||
import os.path
|
import os.path
|
||||||
import struct
|
import struct
|
||||||
from ctypes import c_int, byref, c_uint
|
from ctypes import c_int, byref, c_uint
|
||||||
|
@ -9,7 +8,7 @@ from io import BytesIO
|
||||||
import six
|
import six
|
||||||
from pyglet import image
|
from pyglet import image
|
||||||
from pyglet.gl import *
|
from pyglet.gl import *
|
||||||
from six.moves import zip, range
|
from six.moves import range
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from ._glgeom import bgr_to_rgb, flip_vertical
|
from ._glgeom import bgr_to_rgb, flip_vertical
|
||||||
|
@ -229,21 +228,26 @@ def load_clouds(file):
|
||||||
|
|
||||||
path, width, height, depth, mode, texture = load_image(file, path)
|
path, width, height, depth, mode, texture = load_image(file, path)
|
||||||
|
|
||||||
|
if depth != 1:
|
||||||
|
texture = texture[::depth]
|
||||||
|
|
||||||
buffer = c_uint()
|
buffer = c_uint()
|
||||||
glGenTextures(1, byref(buffer))
|
glGenTextures(1, byref(buffer))
|
||||||
id = buffer.value
|
id = buffer.value
|
||||||
|
|
||||||
pixels = bytearray(len(texture) * 4)
|
|
||||||
white = b'\xff'[0]
|
|
||||||
pixels[:] = itertools.chain.from_iterable(zip(itertools.repeat(white), itertools.repeat(white),
|
|
||||||
itertools.repeat(white),
|
|
||||||
itertools.islice(texture, 0, None, depth)))
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, id)
|
glBindTexture(GL_TEXTURE_2D, id)
|
||||||
|
|
||||||
|
if gl_info.have_version(3) or gl_info.have_extension('GL_ARB_framebuffer_object'):
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, texture)
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D)
|
||||||
|
else:
|
||||||
|
gluBuild2DMipmaps(GL_TEXTURE_2D, 1, width, height, GL_RED, GL_UNSIGNED_BYTE, texture)
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, six.binary_type(pixels))
|
|
||||||
|
if gl_info.have_extension('GL_EXT_texture_filter_anisotropic'):
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, glGetInteger(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT))
|
||||||
|
|
||||||
cache[path] = id
|
cache[path] = id
|
||||||
return id
|
return id
|
||||||
|
|
|
@ -20,6 +20,7 @@ class World(object):
|
||||||
PROGRAMS = {
|
PROGRAMS = {
|
||||||
'sky': ('sky.vertex.glsl', 'sky.fragment.glsl'),
|
'sky': ('sky.vertex.glsl', 'sky.fragment.glsl'),
|
||||||
'planet': ('planet.vertex.glsl', 'planet.fragment.glsl'),
|
'planet': ('planet.vertex.glsl', 'planet.fragment.glsl'),
|
||||||
|
'clouds': ('clouds.vertex.glsl', 'clouds.fragment.glsl'),
|
||||||
'star': ('star.vertex.glsl', 'star.fragment.glsl'),
|
'star': ('star.vertex.glsl', 'star.fragment.glsl'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +53,9 @@ class World(object):
|
||||||
shader.uniform_vec3('u_sun.specular', 0.5, 0.5, 0.5)
|
shader.uniform_vec3('u_sun.specular', 0.5, 0.5, 0.5)
|
||||||
shader.uniform_vec3('u_sun.position', 0, 0, 0)
|
shader.uniform_vec3('u_sun.position', 0, 0, 0)
|
||||||
shader.uniform_float('u_sun.intensity', 1)
|
shader.uniform_float('u_sun.intensity', 1)
|
||||||
|
|
||||||
|
shader = self.activate_shader('clouds')
|
||||||
|
shader.uniform_vec3('u_sun', 0, 0, 0)
|
||||||
self.activate_shader(None)
|
self.activate_shader(None)
|
||||||
|
|
||||||
def _load_programs(self):
|
def _load_programs(self):
|
||||||
|
|
Loading…
Reference in a new issue