package.path = package.path .. ";./assets/scripts/?.lua"
require "luascape.render"
require "luascape.graphics"
require "luascape.objects"
require "luascape.scene"
require "materials"
require "settings"
require "tinyandbig"

function initMaterial(levelRenderPass, shader)
  local shadowMapRenderPass = materials.getShadowMapRenderPass(levelRenderPass)
  if (not shadowMapRenderPass) then
    return
  end 
  local textureState = shader:getOrCreateTextureState()
  textureState:setAnisotropy(0, settings.hatch.anisotropy)
  if settings.hatchRGB then
    local texture = Texture.loadFromFile("pur1-3RGB.dds")
    textureState:setTexture(2, texture)
    textureState:setAnisotropy(2, settings.hatch.anisotropy)
    local texture = Texture.loadFromFile("pur4-6RGB.dds")
    textureState:setTexture(3, texture)
    textureState:setAnisotropy(3, settings.hatch.anisotropy)
  else
    for i=1,6 do
      local texture = Texture.loadFromFile("pur_0"..i..".png")
      textureState:setTexture(8 - i, texture)
    end
  end
  
  local shadowMap = shadowMapRenderPass.shadowMap
  local shadowTexture = materials.getBlurredShadowTexture(levelRenderPass)

  local hatchVertexShader, hatchFragmentShader
  if settings.perPixelHatch then
    hatchVertexShader = "hatchingpp_vp.cg"
    if settings.hatchRGB then
      hatchFragmentShader = "hatchingpp_rgb_fp.cg"
    else
      hatchFragmentShader = "hatchingpp_fp.cg"
    end
    textureState:setTexture(1, shadowTexture)
  else
    hatchVertexShader = "hatching_vp.cg"
    hatchFragmentShader = "hatching_fp.cg"
    ShadowMapRenderPass.setupTextureState(textureState, 1, shadowMap)
  end
  
  local shadowLight = shadowMapRenderPass.light
  local hatchLight = levelRenderPass.diffuseLight

  local shaderProgramState = graphics.createShaderProgramState(
    hatchVertexShader, {
      ModelViewProjectionMatrixUniform(),
      ModelMatrixUniform(),
    },
    hatchFragmentShader, {
      ColorUniform(Color.WHITE, "blendColor"),
      VectorUniform(Vector(settings.camera.near, settings.camera.far, settings.hatch.fadeNear, settings.hatch.fadeFar), "cameraSettings")
    }                   
  )

  local hatchLayersUniform = FloatUniform(settings.hatchLayers, "hatchLayers")
  if settings.perPixelHatch then
    shaderProgramState.fragmentUniforms:add(hatchLayersUniform)
  else
    shaderProgramState.vertexUniforms:add(hatchLayersUniform)
  end

  shader.shaderProgramState = shaderProgramState
  
  local materialState = shader:getOrCreateMaterialState()
  materialState.vertexColor = Color.BLACK
end

function updateMaterial(levelRenderPass, shader, material)
  local factor = 1
  local node = material.node
  if node then
    local visual = node.visual
    local min = Vector()
    local max = Vector()
    visual:getExtent(min, max)
  
    local boundingBox = AxisAlignedBox(min, max)
    factor = math.max(boundingBox:width(), boundingBox:depth(), boundingBox:height())
    factor = factor / 100 / settings.hatchScale
  end

  if (not shader.shaderProgramState) then
    return;
  end 
  
  local shaderProgramState = shader.shaderProgramState:clone()
  shaderProgramState.vertexUniforms:add(FloatUniform(factor, "hatchScale"))
  shader.shaderProgramState = shaderProgramState
  
--[[  local textureState = shader.textureState
  if not textureState.textureUnits[0].texture then
    textureState:setTexture(0, Texture.loadFromFile("white.dds"))
  end]]
end

function createHatchShader(levelRenderPass)
  local shader = Shader()
  initMaterial(levelRenderPass, shader)
  return shader
end
