Skip to content

Add Fake 3D

NuriYuri requested to merge add-fake-3d into development

MR Description

This adds Fake3D utility for PSDK.

In order to work file you need the following:

  1. Enable the Fake3D by setting Fake3D::ENABLED to true (before the window opens)
  2. Add the shader files to graphics/shaders:

fake_3d.vert

#version 120

uniform mat4 camera;
uniform float z;

void main() {
  vec4 vert = gl_Vertex;
  vert.z = z;
  gl_Position = camera * vert;
  vert.z = gl_Vertex.z;
  gl_TexCoord[0].xy = (gl_TextureMatrix[0] * gl_MultiTexCoord0).xy;
  gl_FrontColor = gl_Color;
}

fake_3d.frag

#version 120

uniform sampler2D texture;

void main() {
  gl_FragColor = texture2D(texture, gl_TexCoord[0].xy) * gl_Color;
}

Note: Those shaders are loaded only if Fake3D::ENABLED is true. This way this utility won't break project missing the shaders and not actually using them!

Tests to realize

Add the following script:

class Fake3DScene < GamePlay::BaseCleanUpdate
  class Sprite3D < Sprite
    prepend Fake3D::Sprite3D
  end
  private

  def create_graphics
    super
    @sprites = [
      create_sprite(0, 20, 2, '002'),
      create_sprite(20, 20, 2, '002'),
      create_sprite(0, 0, 2, '002'),
      create_sprite(20, 0, 2, '002'),
      create_sprite(0, 0, 1),
      create_sprite(20, 0, 1),
      create_sprite(20, 20, 1),
      create_sprite(0, 20, 1),
    ]
    @camera = Fake3D::Camera.new(@viewport)
    @camera.apply_to(@sprites)
    @stack = UI::SpriteStack.new(@viewport)
    @position = @stack.add_text(0, 0, 320, 16, 'Position:    0,    0,    1')
    @position.z = 10_000
    @rotation = @stack.add_text(0, 16, 320, 16, 'Rotation:   0,   0,   0')
    @rotation.z = 10_000
    @yaw = 0
    @z = 1
  end

  def update_mouse(moved)
    return if !moved && Mouse.wheel_delta == 0
    if Mouse.press?(:LEFT)
      @yaw += Mouse.wheel_delta / 10.0
      @yaw %= 360
      @camera.set_rotation(@yaw, Mouse.x - 160, Mouse.y - 120)
      @camera.apply_to(@sprites)
      @rotation.text = "Rotation: #{@camera.yaw.round.to_s.rjust(3)}, #{@camera.pitch.round.to_s.rjust(3)}, #{@camera.roll.round.to_s.rjust(3)}"
    elsif Mouse.press?(:RIGHT)
      @z += Mouse.wheel_delta / 10.0
      @z = @z.clamp(0.001, 20)
      @camera.set_position(Mouse.x - 160, Mouse.y - 120, @z)
      @camera.apply_to(@sprites)
      @position.text = "Position: #{@camera.x.to_s.rjust(4)}, #{@camera.y.to_s.rjust(4)}, #{@camera.z.to_s.rjust(4)}"
    end
  end

  def create_sprite(x, y, z, img = '001')
    sprite = Sprite3D.new(@viewport)
    sprite.load(img, :icon)
    sprite.set_origin(16, 16)
    sprite.set_position(x, -y, z)
    sprite.opacity = 180
    return sprite
  end
end

Call it using $scene.call_scene(Fake3DScene)

Enjoy.

Merge request reports