Партнерка на США и Канаду по недвижимости, выплаты в крипто

  • 30% recurring commission
  • Выплаты в USDT
  • Вывод каждую неделю
  • Комиссия до 5 лет за каждого referral

Иван Андреев

andreev. *****@***com

Основы 3Д. Точечные источники света

В рамках данной работы учащийся должен разработать шейдер для освещения объекта от точечных источников света.

Задание на работу:

Использую библиотеку графических примитивов отобразить на экране несколько моделей чайников.

Разработать шейдер освещения от точечных источников света.

Расположить 3 точечных источника света с разными цветами.

Теоретическая часть:

Основной теоретический материал, необходимый для данного задания, подробно описан в лекционных и практических занятиях.

Типы источников света

Источники направленного света (directional light sources)

Источник направленного света находится в бесконечно-удаленной точке. В этом случае допустимо считать, что все лучи света от него распространяются параллельно и для всех точек можно использовать один и тот же вектор направления освещения. Хорошим примером такого источника света является Солнце.

Для источников направленного света использование модели Блинна-Фонга оказывается весьма выгодным. В предположении о постоянстве вектора взгляда , вектор полупути может быть вычислен единожды для источника и, далее использоваться на протяжении всех вычислений. В этом случае расчет зеркальной компоненты освещенности будет почти так же прост, как для рассеянной составляющей.

Параметры и расчетная формула

Параметрами источника направленного света будут вектор направления (для расчета рассеянной компоненты) и вектор полупути (для расчета зеркальной компоненты). Суммарный вклад в освещение от источника направленного света рассчитывается по формуле:

НЕ нашли? Не то? Что вы ищете?

Точечные источники света (point light sources)

В отличие от источников направленного света, точечные источники находятся в определенной точке пространства с конечными координатами, и свет от них распространяется равномерно по всем направлениям. При расчете освещенности в точке будет учитываться направление на такой источник.

Также для точечных источников учитывается эффект поглощения света, когда интенсивность излучения уменьшается с расстоянием (distance attenuation). Убывание интенсивности излучения с расстоянием задается следующей формулой:

где - расстояние от освещаемой точки до источника света.

Параметры и расчетная формула

Параметрами точечного источника света будут его положение в пространстве и три коэффициента для расчета затухания. Суммарный вклад в освещение от точечного источника света рассчитывается по формуле:

Прожекторы (spot light sources)

Такие источники света являются простой имитацией реальных прожекторов, которые используются, к примеру, в театре для создания мощного луча света в определенном направлении. Свет от такого источника распространяется лишь в определенном направлении и получается конус света. Обеспечивается это с помощью наложения ограничений на вектор направления от освещаемой точки до источника света.

У прожекторов, по сравнению с точечными источниками света добавляются два новых параметра: направление центрального освещения , половинный угол отсечения ц и коэффициент поглощения kspotatt. Далее вычисляется величина fspotatt:

Прим. Косинус в первой четверти убывающая функция, поэтому приведенные выше условия будут верными, хотя для углов стоят противоположные знаки в неравенствах. Угол отсечения ц Є (0; 90°). Если ц = 90°, то прожектор вырождается в точечный источник света.

Параметры и расчетная формула

Параметрами прожектора будут его положение в пространстве, три коэффициента для расчета затухания, направление центрального освещения, половинный угол отсечения и коэффициент поглощения.

Суммарный вклад в освещение от прожектора рассчитывается по формуле:

Суммарное освещение

На сцене может находиться несколько источников освещения. В этом случае суммарное освещение создаваемое источниками света будет равно сумме вкладов, вносимых каждым источником:

где Ij – вклад вносимый j-м источником света. Если учесть способность материала излучать свет и глобальную фоновую освещенность сцены, то итоговая формула будет:

После расчета величин IR, IG, IB в конкретной вершине эти значения могут быть больше единицы. В этом случае существует три способа нормализации:

Отсечение (clamping): если компонента больше единицы, то она приравнивается единице. Если компонента меньше нуля, то она приравнивается нулю. Нормализация в вершине: считается минимум и максимум из IR, IG, IB в конкретной вершине. После этого диапазон [Imin; Imax] линейным преобразованием переводится в диапазон [max(0, Imin); min(Imax, 1)] (для конкретной вершины). Нормализация по всем вершинам: считается минимум и максимум из IR, IG, IB во всех вершинах. После этого диапазон [Imin; Imax] линейным преобразованием переводится в диапазон [max(0, Imin); min(Imax, 1)] (для всех вершин).

[http://pgraphics. info/3D/lighting/light_sources. php]

Реализация:

using System;

using System. Collections. Generic;

using System. Linq;

using Microsoft. Xna. Framework;

using Microsoft. Xna. Framework. Audio;

using Microsoft. Xna. Framework. Content;

using Microsoft. Xna. Framework. GamerServices;

using Microsoft. Xna. Framework. Graphics;

using Microsoft. Xna. Framework. Input;

using Microsoft. Xna. Framework. Media;

using Microsoft. Xna. ;

using Microsoft. Xna. Framework. Storage;

using Primitives3D;

namespace Lab8

{

  /// <summary>

  /// This is the main type for your game

  /// </summary>

  public class Game1 : Microsoft. Xna. Framework. Game

  {

  GraphicsDeviceManager graphics;

  SpriteBatch spriteBatch;

  TeapotPrimitive teapot;

  Effect effect;

  SpherePrimitive pointLight;

  public Game1()

  {

  graphics = new GraphicsDeviceManager(this);

  Content. RootDirectory = "Content";

  }

  /// <summary>

  /// Allows the game to perform any initialization it needs to before starting to run.

  /// This is where it can query for any required services and load any non-graphic

  /// related content.  Calling base. Initialize will enumerate through any components

  /// and initialize them as well.

  /// </summary>

  protected override void Initialize()

  {

  // TODO: Add your initialization logic here

  teapot = new TeapotPrimitive(GraphicsDevice);

  pointLight = new SpherePrimitive(GraphicsDevice, 0.1f, 20);

  base. Initialize();

  }

  /// <summary>

  /// LoadContent will be called once per game and is the place to load

  /// all of your content.

  /// </summary>

  protected override void LoadContent()

  {

  // Create a new SpriteBatch, which can be used to draw textures.

  spriteBatch = new SpriteBatch(GraphicsDevice);

  // TODO: use this. Content to load your game content here

  effect = Content. Load<Effect>("light");

  }

  /// <summary>

  /// UnloadContent will be called once per game and is the place to unload

  /// all content.

  /// </summary>

  protected override void UnloadContent()

  {

  // TODO: Unload any non ContentManager content here

  }

  /// <summary>

  /// Allows the game to run logic such as updating the world,

  /// checking for collisions, gathering input, and playing audio.

  /// </summary>

  /// <param name="gameTime">Provides a snapshot of timing values.</param>

  protected override void Update(GameTime gameTime)

  {

  // Allows the game to exit

  if (GamePad. GetState(PlayerIndex. One).Buttons. Back == ButtonState. Pressed)

  this. Exit();

  // TODO: Add your update logic here

  base. Update(gameTime);

  }

  /// <summary>

  /// This is called when the game should draw itself.

  /// </summary>

  /// <param name="gameTime">Provides a snapshot of timing values.</param>

  protected override void Draw(GameTime gameTime)

  {

  GraphicsDevice. Clear(Color. Black);

  // TODO: Add your drawing code here

  Vector3 cameraPosition = new Vector3(0, 0, 8);

  Matrix world = Matrix. CreateRotationY((float)gameTime. TotalGameTime. TotalSeconds);

  Matrix view = Matrix. CreateLookAt(cameraPosition, Vector3.Zero, Vector3.Up);

  Matrix proj = Matrix. CreatePerspectiveFieldOfView(MathHelper. ToRadians(45), GraphicsDevice. Viewport. AspectRatio, 0.1f, 20);

  Vector3 lightPos0 = new Vector3(0, -1, 1);

  Vector3 lightPos1 = new Vector3(1, 1, 1);

  Vector3 lightPos2 = new Vector3(-2, 0, 0);

  // Источники света

  pointLight. Draw(Matrix. CreateTranslation(lightPos0), view, proj, Color. Blue);

  pointLight. Draw(Matrix. CreateTranslation(lightPos1), view, proj, Color. Blue);

  pointLight. Draw(Matrix. CreateTranslation(lightPos2), view, proj, Color. Blue);

  effect. CurrentTechnique = effect. Techniques["Phong"];

  effect. Parameters["LightPosition0"].SetValue(lightPos0);

  effect. Parameters["LightPosition1"].SetValue(lightPos1);

  effect. Parameters["LightPosition2"].SetValue(lightPos2);

  effect. Parameters["AmbientColor0"].SetValue(new Vector4(0.1f, 0.1f, 0.1f, 1));

  effect. Parameters["DiffuseColor0"].SetValue(new Vector4(0.5f, 0f, 0f, 1));

  effect. Parameters["SpecularColor0"].SetValue(new Vector4(1, 0, 0, 1));

  effect. Parameters["AmbientColor1"].SetValue(new Vector4(0.1f, 0.1f, 0.1f, 1));

  effect. Parameters["DiffuseColor1"].SetValue(new Vector4(0, 0.5f, 0.5f, 1));

  effect. Parameters["SpecularColor1"].SetValue(new Vector4(0, 1, 1, 1));

  effect. Parameters["AmbientColor2"].SetValue(new Vector4(0.1f, 0.1f, 0.1f, 1));

  effect. Parameters["DiffuseColor2"].SetValue(new Vector4(0.5f, 0.5f, 0.5f, 1));

  effect. Parameters["SpecularColor2"].SetValue(new Vector4(1, 1, 1, 1));

  effect. Parameters["Eye"].SetValue(cameraPosition);

  effect. Parameters["World"].SetValue(world);

  effect. Parameters["View"].SetValue(view);

  effect. Parameters["Projection"].SetValue(proj);

  effect. Parameters["Color"].SetValue(new Vector4(1, 1, 0, 1));

  teapot. Draw(effect);

  effect. Parameters["World"].SetValue(world * Matrix. CreateTranslation(0, 2, 0));

  teapot. Draw(effect);

  effect. Parameters["World"].SetValue(world * Matrix. CreateTranslation(-3, 0, 0));

  teapot. Draw(effect);

  base. Draw(gameTime);

  }

  }

}

Шейдер light. fx:

float4x4 World;

float4x4 View;

float4x4 Projection;

float ka = 1;

float kd = 0.5;

float ks = 1;

float SpecularPower = 4;

// Собственный цвет объекта

float4 Color = float4(1, 0, 0, 1);

float4 AmbientColor0 = float4(0.1, 0.1, 0.1, 1);

float4 DiffuseColor0 = float4(1,1,1,1);

float4 SpecularColor0 = float4(1,1,1,1);

float4 AmbientColor1 = float4(0.1, 0.1, 0.1, 1);

float4 DiffuseColor1 = float4(1,1,1,1);

float4 SpecularColor1 = float4(1,1,1,1);

float4 AmbientColor2 = float4(0.1, 0.1, 0.1, 1);

float4 DiffuseColor2 = float4(1,1,1,1);

float4 SpecularColor2 = float4(1,1,1,1);

// Предполагается, что координаты источников света заданы в мировых координатах

float3 LightPosition0 = float3(0,0,2);

float3 LightPosition1 = float3(2,0,0);

float3 LightPosition2 = float3(-2,0,0);

float3 Eye;

// TODO: add effect parameters here.

struct VertexShaderInputPhong

{

  float4 Position : POSITION0;

  float3 Normal : NORMAL;

  // TODO: add input channels such as texture

  // coordinates and vertex colors here.

};

struct VertexShaderOutputPhong

{

  float4 Position : POSITION0;

  float3 WorldPosition : TEXCOORD0;

  float3 Normal : TEXCOORD1;

  // TODO: add vertex shader outputs such as colors and texture

  // coordinates here. These values will automatically be interpolated

  // over the triangle, and provided as input to your pixel shader.

};

VertexShaderOutputPhong VertexShaderFunctionPhong(VertexShaderInputPhong input)

{

  VertexShaderOutputPhong output;

  float4 worldPosition = mul(input. Position, World);

  float4 viewPosition = mul(worldPosition, View);

  float3 worldNormal = normalize(mul(input. Normal, World));

  output. Position = mul(viewPosition, Projection);

  output. WorldPosition = worldPosition;

  output. Normal = worldNormal;

  // TODO: add your vertex shader code here.

  return output;

}

float4 PointLight(float3 LightPosition, float3 worldPosition, float3 worldNormal, float4 AmbientColor, float4 DiffuseColor, float4 SpecularColor)

{

  float4 Ambient = ka * AmbientColor;

  float3 lightDirection = normalize(LightPosition - worldPosition);

  float4 Diffuse = kd * max(0, dot(worldNormal, lightDirection)) * DiffuseColor;

  float3 eyeDirection = normalize(Eye - worldPosition);

  float3 reflectedLight = normalize(reflect(-lightDirection, worldNormal));

  float4 Specular = ks * pow(max(0, dot(eyeDirection, reflectedLight)), SpecularPower) * SpecularColor;

       // для упрощения коэффициент затухания равен 1/d^2

  return (Ambient + Diffuse + Specular) / pow(length(worldPosition-LightPosition), 2);

}

float4 PixelShaderFunctionPhong(VertexShaderOutputPhong input) : COLOR0

{

  // TODO: add your pixel shader code here.

  float3 worldPosition = input. WorldPosition;

  float3 worldNormal = normalize(input. Normal);

  float4 light0 = PointLight(LightPosition0, worldPosition, worldNormal, AmbientColor0, DiffuseColor0, SpecularColor0);

  float4 light1 = PointLight(LightPosition1, worldPosition, worldNormal, AmbientColor1, DiffuseColor1, SpecularColor1);

  float4 light2 = PointLight(LightPosition2, worldPosition, worldNormal, AmbientColor2, DiffuseColor2, SpecularColor2);

  return Color * (light0 + light1 + light2);

}

technique Phong

{

  pass Pass1

  {

  // TODO: set renderstates here.

  VertexShader = compile vs_1_1 VertexShaderFunctionPhong();

  PixelShader = compile ps_3_0 PixelShaderFunctionPhong();

  }

}