Preview

Final render
Simple Skybox

Concept

Since Pine3D does not support textures, we have to create models with triangles to create an environment. The performance impact is minimal as long as we make sure we don't use 100 polygons, as Pine3D can easily render thousands of polygons while maintaining a framerate of 20. The following example will use 31-43 polygons depending on how many mountains have snow.

We can choose to render these models with an Object at 0, 0, 0. Alternatively (recommended), we can decide to not specify the position at all, such that the models are always rendered at the position of the camera, which is what we will do here.

We can render these using a separate table and call to ThreeDFrame.drawObjects to make sure they are always behind other objects that should be drawn.

Tutorial

Plane

Using Pine3D.models we can generate a plane Object with a plane Model just below the camera with a large size and a chosen color.
local plane = ThreeDFrame:newObject(Pine3D.models:plane({
  color = colors.lime,
  size = 100,
  y = -0.1,
}))

Hills

We can use the mountains method to generate mountains, or hills, as we can specify many variables like their color. We generate an Object with the hills Model as follows:
local hills = ThreeDFrame:newObject(Pine3D.models:mountains({
  color = colors.green,
  y = -0.1,
  res = 18,
  scale = 50,
  randomHeight = 0.5,
  randomOffset = 0.5,
}))

Mountains

Finally, we can create a mountains Model with snow. We set snow to true and pick a snowHeight. We choose to have fewer, larger mountains this time:
local mountains = ThreeDFrame:newObject(Pine3D.models:mountains({
  color = colors.lightGray,
  y = -0.1,
  res = 12,
  scale = 100,
  randomHeight = 0.5,
  randomOffset = 0.5,
  snow = true,
  snowHeight = 0.6,
}))

Full example

-- import library
local Pine3D = require("Pine3D")

-- create a new frame
local ThreeDFrame = Pine3D.newFrame()

-- create environment objects
local environmentObjects = {
  ThreeDFrame:newObject(Pine3D.models:mountains({
    color = colors.lightGray,
    y = -0.1,
    res = 12,
    scale = 100,
    randomHeight = 0.5,
    randomOffset = 0.5,
    snow = true,
    snowHeight = 0.6,
  })),
  ThreeDFrame:newObject(Pine3D.models:mountains({
    color = colors.green,
    y = -0.1,
    res = 18,
    scale = 50,
    randomHeight = 0.5,
    randomOffset = 0.5,
  })),
  ThreeDFrame:newObject(Pine3D.models:plane({
    color = colors.lime,
    size = 100,
    y = -0.1,
  })),
}

-- create objects to render normally
local objects = {
  ThreeDFrame:newObject("models/pineapple", 1.5, -0.7, 0, nil, math.pi*0.125, nil)
}

-- render environment before the other objects
ThreeDFrame:drawObjects(environmentObjects)
ThreeDFrame:drawObjects(objects)
ThreeDFrame:drawBuffer()

-- sleep to see the result for a second
sleep(1)