EditableImage not working?

I am working on a little demo place to see about creating custom skyboxes with EditableImages. However, despite the images being created 100% properly and the fields being assigned right, the skybox doesn’t render the image.

I applied the content to an image label to prove that I generate the images properly. Can anyone help me because I am stumped. They added “SkyboxBackContent” etc property fields on the skybox so it should specifically support Content fields. I am at a loss

No skybox exists in the world prior to running the game:
image

Running the game shows ImageLabel rendering properly, skybox not rendering at all:

Looking at explorer shows Sky now exists, and has the fields populated

Code:

-- LocalScript
-- Recommended location: StarterPlayer > StarterPlayerScripts

local Players = game:GetService("Players")
local Lighting = game:GetService("Lighting")
local AssetService = game:GetService("AssetService")

local Player = Players.LocalPlayer
local PlayerGui = Player:WaitForChild("PlayerGui")

--------------------------------------------------
-- CONFIG
--------------------------------------------------

local IMAGE_SIZE = 256

local TopColor = Color3.fromRGB(0, 0, 0)
local BottomColor = Color3.fromRGB(255, 0, 0)

--------------------------------------------------
-- CREATE SKY
--------------------------------------------------

local Sky = Instance.new("Sky")
Sky.CelestialBodiesShown = false

--------------------------------------------------
-- CREATE EDITABLE IMAGES
--------------------------------------------------

local function createImage()
	local image = AssetService:CreateEditableImage({
		Size = Vector2.new(IMAGE_SIZE, IMAGE_SIZE),
	})

	assert(image, "Failed to create EditableImage")

	return image
end

local TopImage = createImage()
local MiddleImage = createImage()
local BottomImage = createImage()

--------------------------------------------------
-- SOLID COLOR IMAGE
--------------------------------------------------

local function fillSolid(image, color)
	image:DrawRectangle(
		Vector2.zero,
		image.Size,
		color,
		0,
		Enum.ImageCombineType.Overwrite
	)
end

--------------------------------------------------
-- VERTICAL GRADIENT
--------------------------------------------------

local function fillVerticalGradient(image, topColor, bottomColor)
	local width = image.Size.X
	local height = image.Size.Y

	-- RGBA = 4 bytes per pixel
	local pixelBuffer = buffer.create(width * height * 4)

	for y = 0, height - 1 do
		local alpha = y / (height - 1)

		local color = topColor:Lerp(bottomColor, alpha)

		local r = math.round(color.R * 255)
		local g = math.round(color.G * 255)
		local b = math.round(color.B * 255)

		for x = 0, width - 1 do
			local index = (y * width + x) * 4

			buffer.writeu8(pixelBuffer, index + 0, r)
			buffer.writeu8(pixelBuffer, index + 1, g)
			buffer.writeu8(pixelBuffer, index + 2, b)
			buffer.writeu8(pixelBuffer, index + 3, 255)
		end
	end

	image:WritePixelsBuffer(
		Vector2.zero,
		image.Size,
		pixelBuffer
	)
end

--------------------------------------------------
-- GENERATE IMAGES
--------------------------------------------------

fillSolid(TopImage, TopColor)

fillVerticalGradient(
	MiddleImage,
	TopColor,
	BottomColor
)

fillSolid(BottomImage, BottomColor)

--------------------------------------------------
-- CONVERT TO CONTENT
--------------------------------------------------

local TopContent = Content.fromObject(TopImage)
local MiddleContent = Content.fromObject(MiddleImage)
local BottomContent = Content.fromObject(BottomImage)

--------------------------------------------------
-- APPLY TO SKYBOX
--------------------------------------------------

Sky.SkyboxUpContent = TopContent
Sky.SkyboxDownContent = BottomContent

Sky.SkyboxFrontContent = MiddleContent
Sky.SkyboxBackContent = MiddleContent
Sky.SkyboxLeftContent = MiddleContent
Sky.SkyboxRightContent = MiddleContent

--------------------------------------------------
-- DEBUG GUI
--------------------------------------------------

local ScreenGui = Instance.new("ScreenGui")
ScreenGui.Name = "EditableSkyDebug"
ScreenGui.ResetOnSpawn = false
ScreenGui.Parent = PlayerGui

local ImageLabel = Instance.new("ImageLabel")
ImageLabel.Name = "GradientPreview"

ImageLabel.Size = UDim2.fromOffset(200, 200)
ImageLabel.Position = UDim2.fromOffset(20, 20)

ImageLabel.BackgroundColor3 = Color3.fromRGB(30, 30, 30)
ImageLabel.BorderSizePixel = 2

ImageLabel.ImageContent = MiddleContent

ImageLabel.Parent = ScreenGui

--------------------------------------------------
-- OPTIONAL LABEL
--------------------------------------------------

local TextLabel = Instance.new("TextLabel")
TextLabel.Name = "DebugText"

TextLabel.Size = UDim2.fromOffset(200, 24)
TextLabel.Position = UDim2.fromOffset(20, 224)

TextLabel.BackgroundColor3 = Color3.fromRGB(20, 20, 20)
TextLabel.BackgroundTransparency = 0.2

TextLabel.TextColor3 = Color3.new(1, 1, 1)
TextLabel.Text = "Middle EditableImage"
TextLabel.TextSize = 14

TextLabel.Parent = ScreenGui

Sky.Parent = Lighting

If anyone has any ideas as to what’s going on here please share because I have tried just about everything

1 Like

Hey, thanks for posting this! I made the same assumption as you that since a Sky instance now supports Content properties it would automatically work with EditableImage.

You are technically able to dynamically create an EditableImage and render it with a Sky, however you have to “bake” the EditableImage first using AssetService:CreateDataModelContentAsync() (read more in this announcement).

Code
--!strict
-- In a LocalScript parented to a ScreenGui with child ImageLabel
-- Also assumes a Sky instance already exists under Lighting

local AssetService = game:GetService("AssetService")
local Lighting = game:GetService("Lighting")

local image = AssetService:CreateEditableImage({
	Size = Vector2.new(128, 128)
})

local COLOR_BEG = Color3.new(0, 1, 1)
local COLOR_MID = Color3.new(1, 1, 1)
local COLOR_END = Color3.new(1, 0, 1)

for y = 0, image.Size.Y - 1 do
	for x = 0, image.Size.X - 1 do
		
		local n = math.clamp(math.noise(x / 17, y / 17), -0.5, 0.5)
		
		image:DrawRectangle(
			Vector2.new(x, y),
			Vector2.one,
			if n < 0 then COLOR_BEG:Lerp(COLOR_MID, 1 - 2 * math.abs(n)) else COLOR_MID:Lerp(COLOR_END, 2 * n),
			0,
			Enum.ImageCombineType.Overwrite
		)

	end
end



local imageContent = Content.fromObject(image)
script.Parent.ImageLabel.ImageContent = imageContent

local result, bakedContent = AssetService:CreateDataModelContentAsync(imageContent)
Lighting.Sky.SkyboxFrontContent = bakedContent

My theory is that a Sky instance intentionally does not directly support EditableImage because lighting/reflection calculations are too expensive to do on a dynamic skybox (explained a bit in the [Studio Beta] Beyond Static Skies: Rotate Your Worlds with SkyboxOrientation! announcement).

Hopefully this isn’t too restrictive for your use case!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.