0

i am creating a small game using Ursina and i have code which generates a terrain mesh using perlin noise. the mesh itself renders but i can't put textures on it properly and shaders do not work on it, it just renders as a solid colour.

screenshot of the game - terrain is all one colour and not shaded

here's my code

`

from ursina import *
from ursina.prefabs.first_person_controller import FirstPersonController
from ursina.shaders import lit_with_shadows_shader
from perlin_noise import PerlinNoise
import time

game = Ursina()

window.title = "new_game"
window.borderless = False
window.fps_counter.enabled = True
window.exit_button.visible = False
window.fullscreen = False

groundTexture = load_texture("assets/placeholder.png")
crosshairTexture = load_texture("assets/crosshair.png")

crosshair = Entity(model = "cube", texture = crosshairTexture, parent = camera.ui, scale = 0.2)
crosshair.always_on_top = True

title = Text("new game", origin = (6.825, -19))
coordinates = Text("", origin = (3.35, -8))

mode = 1

size = 20
level =  size / 10
seed = random.randint(1, 1000000)
noise = PerlinNoise(octaves = 3, seed = seed)

vertices = [0] * ((size + 1) * (size + 1))

i = 0

for z in range(size + 1):

    for x in range(size + 1):

        y = level * noise([x / size, z / size])

        vertices[i] = x, y, z

        i = i + 1

triangles = [0] * (size * size * 6)

vert = 0
tris = 0

for z in range(size):

    for x in range(size):

        triangles[tris + 0] = vert + 0
        triangles[tris + 1] = vert + size + 1
        triangles[tris + 2] = vert + 1
        triangles[tris + 3] = vert + 1
        triangles[tris + 4] = vert + size + 1
        triangles[tris + 5] = vert + size + 2

        vert = vert + 1
        tris = tris + 6

    vert = vert + 1

triangles.reverse() # array is made counter-clockwise

def input(key):

    if key == "escape":
        
        Audio(sound_file_name = "assets/tick.wav")

        time.sleep(0.25)

        exit()

def update():

    coordinates.text = "coordinates (x, y, z):\n" + str(player.position)

# MAIN

terrainMesh = Mesh(vertices, triangles)

terrain = Entity(model = terrainMesh, collider = "mesh", texture = "grass_big", shader = lit_with_shadows_shader)

box = Entity(model = "cube", collider = "mesh", texture = "white_cube", position = (10, 5, 10), shader = lit_with_shadows_shader)

pivot = Entity()
DirectionalLight(parent=pivot, x = 10, y = 10, z = 15, shadows = True, rotation = (45, -45, 45))

if mode == 1:
    
    player = FirstPersonController()

if mode == 2:

    player = EditorCamera()

player.position = (10, 5, 10)
    
game.run()

`

i have tried looking into how to normalise the mesh or use shaders with it but there is practically no helpful documentation on it whatsoever. i wrote the code that generates the mesh but i don't know enough about shaders and normalisation to fix the issue myself. i was wondering if there's a built in function that does this? (i have tried a few and i didn't know how to use them/they didn't work) any help is much appreciated, thanks

smivvys
  • 1
  • 1

1 Answers1

0

How should the texture map to the model? You have to define this by giving it uvs.

UVs are two-dimensional texture coordinates that correspond with the vertex information for your geometry. UVs are vital because they provide the link between a surface mesh and how an image texture gets applied onto that surface. They are basically marker points that control which pixels on the texture correspond to which vertex on the 3D mesh. https://www.pluralsight.com/blog/film-games/understanding-uvs-love-them-or-hate-them-theyre-essential-to-know

To do this with ursina, give the Mesh a list of two dimensional coordinates, one Vec2 for each vertex.

pokepetter
  • 1,383
  • 5
  • 8