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
|
||||
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.orbit import KeplerOrbit
|
||||
from punyverse.texture import get_best_texture, load_clouds
|
||||
|
@ -32,9 +32,14 @@ class Entity(object):
|
|||
def mv_matrix(self):
|
||||
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):
|
||||
self.model_matrix = None
|
||||
self.mv_matrix = None
|
||||
self.mvp_matrix = None
|
||||
x, y, z = self.location
|
||||
dx, dy, dz = self.direction
|
||||
self.location = x + dx, y + dy, z + dz
|
||||
|
@ -316,8 +321,9 @@ class SphericalBody(Body):
|
|||
atm_texture = atmosphere_data.get('diffuse_texture', None)
|
||||
cloud_texture = atmosphere_data.get('cloud_texture', None)
|
||||
if cloud_texture is not None:
|
||||
self.cloud_texture = get_best_texture(cloud_texture, loader=load_clouds)
|
||||
self.clouds = Sphere(self.radius + 2, division, division)
|
||||
self.cloud_transparency = get_best_texture(cloud_texture, loader=load_clouds)
|
||||
self.cloud_radius = self.radius + 2
|
||||
self.clouds = self._get_sphere(division, tangent=False)
|
||||
|
||||
if atm_texture is not None:
|
||||
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_mat4('u_modelMatrix', self.model_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)
|
||||
glBindTexture(GL_TEXTURE_2D, self.texture)
|
||||
|
@ -395,7 +401,7 @@ class SphericalBody(Body):
|
|||
def _draw_star(self):
|
||||
shader = self.world.activate_shader('star')
|
||||
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)
|
||||
glBindTexture(GL_TEXTURE_2D, self.texture)
|
||||
|
@ -436,17 +442,30 @@ class SphericalBody(Body):
|
|||
self.atmosphere.draw()
|
||||
|
||||
def _draw_clouds(self):
|
||||
with glRestore(GL_ENABLE_BIT | GL_TEXTURE_BIT):
|
||||
glLoadMatrixf(self.mv_matrix)
|
||||
glEnable(GL_BLEND)
|
||||
glEnable(GL_ALPHA_TEST)
|
||||
glEnable(GL_CULL_FACE)
|
||||
glDisable(GL_LIGHTING)
|
||||
glEnable(GL_TEXTURE_2D)
|
||||
glEnable(GL_BLEND)
|
||||
shader = self.world.activate_shader('clouds')
|
||||
shader.uniform_float('u_radius', self.cloud_radius)
|
||||
shader.uniform_mat4('u_modelMatrix', self.model_matrix)
|
||||
shader.uniform_mat4('u_mvpMatrix', self.mvp_matrix)
|
||||
|
||||
glCullFace(GL_BACK)
|
||||
glBindTexture(GL_TEXTURE_2D, self.cloud_texture)
|
||||
self.clouds.draw()
|
||||
glActiveTexture(GL_TEXTURE0)
|
||||
glBindTexture(GL_TEXTURE_2D, self.cloud_transparency)
|
||||
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):
|
||||
with glRestore(GL_ENABLE_BIT | GL_TEXTURE_BIT):
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
import sys
|
||||
from ctypes import pointer, byref, create_string_buffer, POINTER, cast
|
||||
|
||||
from pyglet.gl import *
|
||||
|
@ -39,11 +40,15 @@ class Program(object):
|
|||
succeeded = GLint()
|
||||
log_length = GLint()
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, byref(succeeded))
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, byref(log_length))
|
||||
buffer = create_string_buffer(log_length.value + 1)
|
||||
glGetShaderInfoLog(shader, log_length.value, None, buffer)
|
||||
|
||||
if not succeeded:
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, byref(log_length))
|
||||
buffer = create_string_buffer(log_length.value + 1)
|
||||
glGetShaderInfoLog(shader, log_length.value, None, buffer)
|
||||
raise CompileError(buffer.value)
|
||||
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):
|
||||
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 mat3 v_TBN;
|
||||
|
||||
out vec4 o_fragColor;
|
||||
|
||||
struct Surface {
|
||||
sampler2D diffuseMap;
|
||||
bool hasNormal;
|
||||
|
@ -49,5 +51,5 @@ void main() {
|
|||
emission *= u_planet.emission * (1 - min(diffuseIntensity * 2, 1));
|
||||
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
|
||||
|
||||
in vec2 v_uv;
|
||||
out vec4 o_fragColor;
|
||||
uniform sampler2D u_skysphere;
|
||||
|
||||
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
|
||||
|
||||
in vec2 v_uv;
|
||||
out vec4 o_fragColor;
|
||||
uniform sampler2D u_emission;
|
||||
|
||||
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
|
||||
|
||||
import itertools
|
||||
import os.path
|
||||
import struct
|
||||
from ctypes import c_int, byref, c_uint
|
||||
|
@ -9,7 +8,7 @@ from io import BytesIO
|
|||
import six
|
||||
from pyglet import image
|
||||
from pyglet.gl import *
|
||||
from six.moves import zip, range
|
||||
from six.moves import range
|
||||
|
||||
try:
|
||||
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)
|
||||
|
||||
if depth != 1:
|
||||
texture = texture[::depth]
|
||||
|
||||
buffer = c_uint()
|
||||
glGenTextures(1, byref(buffer))
|
||||
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)
|
||||
|
||||
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_MIN_FILTER, GL_LINEAR)
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, six.binary_type(pixels))
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
|
||||
|
||||
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
|
||||
return id
|
||||
|
|
|
@ -20,6 +20,7 @@ class World(object):
|
|||
PROGRAMS = {
|
||||
'sky': ('sky.vertex.glsl', 'sky.fragment.glsl'),
|
||||
'planet': ('planet.vertex.glsl', 'planet.fragment.glsl'),
|
||||
'clouds': ('clouds.vertex.glsl', 'clouds.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.position', 0, 0, 0)
|
||||
shader.uniform_float('u_sun.intensity', 1)
|
||||
|
||||
shader = self.activate_shader('clouds')
|
||||
shader.uniform_vec3('u_sun', 0, 0, 0)
|
||||
self.activate_shader(None)
|
||||
|
||||
def _load_programs(self):
|
||||
|
|
Loading…
Reference in a new issue