» »

WPF 3d prostor - Spotlight, ne znam uporabljat

WPF 3d prostor - Spotlight, ne znam uporabljat

Tutankhamun ::

Zdej sem se mau začet učit 3d grafiko. Narisal sem en prostor polovico kocke, in postavil v prostor spot light. Fora je v tem da mi tiste polovico kocke sploh ne osvetli...

 spot light v prostoru

spot light v prostoru



Js bi rad da je lučka na lokaciji 2,1,2 kot na slikci, sveti pa na ploskev y-z. se pravi bi mogla svetit v negativni x, se pravi 1,0,0. Ampak nič ne dela.

Tko mam nastavljen
<SpotLight Color="Red" OuterConeAngle="20" InnerConeAngle="20" Position="2,1,2" Direction="-1,0,0" />


Kako se to uporablja ker mi ni nč jasn.
AMD Phenom QUAD 9950 Black Edition, 8GB

Senitel ::

Dva možna problema:
1. Normale kocke kažejo navzven (kako narediš ta del kocke?) in je rezultat črn, ker je luč na notranji strani.
2. Osvetlitev se skoraj 100% ne računa za vsak pixel ampak zgolj za vsak vertex oziroma oglišče in glede na kote je tudi oglišče (0,0,0) izven dosega spotlighta. Tako da ali napišeš pixel shader (se to da? :)) ali pa moraš stranice naredit dosti bolj fine. Namesto 2x2 vertexa za stranico vsaj kakšne 10x10, odvisno kako veliko sliko hočeš naredit, oziroma kdaj boš zadovoljen z rezultatom.

Tutankhamun ::

Point3D A = new Point3D(0, 0, 5);
Point3D B = new Point3D(0, 0, 0);
Point3D C = new Point3D(5, 0, 0);
Point3D D = new Point3D(5, 5, 0);
Point3D E = new Point3D(0, 5, 0);
Point3D F = new Point3D(0, 5, 5);
Point3D G = new Point3D(5, 0, 5);

////////////////

mesh.Positions.Add(A);
mesh.Positions.Add(B);
mesh.Positions.Add(C);
mesh.Positions.Add(D);
mesh.Positions.Add(E);
mesh.Positions.Add(F);
mesh.Positions.Add(G);

mesh.TriangleIndices.Add(5);
mesh.TriangleIndices.Add(1);
mesh.TriangleIndices.Add(4);

mesh.TriangleIndices.Add(0);
mesh.TriangleIndices.Add(1);
mesh.TriangleIndices.Add(5);

mesh.TriangleIndices.Add(1);
mesh.TriangleIndices.Add(3);
mesh.TriangleIndices.Add(4);

mesh.TriangleIndices.Add(1);
mesh.TriangleIndices.Add(2);
mesh.TriangleIndices.Add(3);

mesh.TriangleIndices.Add(0);
mesh.TriangleIndices.Add(6);
mesh.TriangleIndices.Add(1);

mesh.TriangleIndices.Add(1);
mesh.TriangleIndices.Add(6);
mesh.TriangleIndices.Add(2);


<PerspectiveCamera 
 FarPlaneDistance="100"
 LookDirection="-20,-4,-20"
 UpDirection="0,1,0"
 NearPlaneDistance="1" 
 Position="20,4,20" 
 FieldOfView="70" />
AMD Phenom QUAD 9950 Black Edition, 8GB

Zgodovina sprememb…

Senitel ::

Torej oboje... :)
Najprej moraš za vsak point/vertex dodat še normalo (mesh.Normals.Add(vector)), ki mora kazat noter (in je ista za celo ploskev).
Potem moraš pa še precej več vertexo naredit. Recimo dve for zanki kjer gre najprej x od 0 do 5 v korakih po 0.1 potem pa še isto za y.

Tutankhamun ::

Aha ja zdej štekam. Če pa dam lučko bol široko pol pa seže do teh #D Point pol se pa vid luč. Al pa če luč usmerm v 0,0,0.
Zdej štekam to kar si napisu, hvala.
AMD Phenom QUAD 9950 Black Edition, 8GB

Senitel ::

Tako je. Lahko tud samo povečaš kote, ampak potem rezultat ne bo ravno spotlight.
Dobil boš nekaj takega:

In ne:

Zgodovina sprememb…

  • spremenil: Senitel ()

Tutankhamun ::

Ok, sem nekaj spacau skupi. Sm hotu narest to kar si ti. Samo eno ploskev, pa lučko.
Nevem kako se ploskev riše, če pogledaš kodo pa poveš a se ploskev tako riše?

MeshGeometry3D mesh = new MeshGeometry3D();

const float _2WDT = 0.1F;
const float SIZE = 5.0F;
int i = 3;
Vector3D normal = new Vector3D(0, 1, 0);

for (float x = 0; x < SIZE; x += _2WDT)
{
	for (float z = 0; z < SIZE; z += _2WDT)
	{
		mesh.Positions.Add(new Point3D(x, 0, z)); // A
		mesh.Positions.Add(new Point3D(x + _2WDT, 0, z)); // B
		mesh.Positions.Add(new Point3D(x + _2WDT, 0, z + _2WDT)); // C
		mesh.Positions.Add(new Point3D(x, 0, z + _2WDT)); // D

		mesh.Normals.Add(normal);
		mesh.Normals.Add(normal);
		mesh.Normals.Add(normal);
		mesh.Normals.Add(normal);

		mesh.TriangleIndices.Add(i);
		mesh.TriangleIndices.Add(i - 2);
		mesh.TriangleIndices.Add(i - 3);

		mesh.TriangleIndices.Add(i);
		mesh.TriangleIndices.Add(i - 1);
		mesh.TriangleIndices.Add(i - 2);

		i += 4;
	}
}

Material material = new DiffuseMaterial(new SolidColorBrush(Colors.Blue));
GeometryModel3D myGeometryModel3D = new GeometryModel3D(mesh, material);

SpotLight slight = new SpotLight(Color.FromRgb(100, 100, 100), new Point3D(2.5, 2, 2.5), new Vector3D(0, -1, 0), 20, 5);

Model3DGroup myModel3DGroup = new Model3DGroup();
myModel3DGroup.Children.Add(myGeometryModel3D);
myModel3DGroup.Children.Add(slight);

ModelVisual3D myModelVisual3D = new ModelVisual3D ()
myModelVisual3D.Content = myModel3DGroup;

this.mainViewport.Children.Add(myModelVisual3D);


<Window x:Class="test.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="527" Width="682">
    <Grid>
        <DockPanel 
          Width="Auto" 
          VerticalAlignment="Stretch" 
          Height="Auto" 
          HorizontalAlignment="Stretch" 
          Grid.ColumnSpan="1" 
          Grid.Column="0" 
          Grid.Row="0" 
          Margin="0,0,0,0" 
          Grid.RowSpan="1" Background="Black">
            <Viewport3D Name="mainViewport" ClipToBounds="True">
                <Viewport3D.Camera>
                    <PerspectiveCamera 
	                  FarPlaneDistance="100"
	                  LookDirection="0,-15,0"
	                  UpDirection="0,0,-1"
	                  NearPlaneDistance="1" 
	                  Position="2,15,2" 
	                  FieldOfView="70" />
                </Viewport3D.Camera>
                <ModelVisual3D>
                    <ModelVisual3D.Content>
                        <DirectionalLight Color="Blue" Direction="0,-1,0" />
						<!--<SpotLight Color="White" OuterConeAngle="50" InnerConeAngle="5" Position="2.5,3,2.5" Direction="0,-1,0" />-->
					</ModelVisual3D.Content>
                </ModelVisual3D>
            </Viewport3D>
        </DockPanel>
    </Grid>
</Window>


Fora pa je da lučke SpotLight sploh ne vidm, če je DirectionalLight uklopljena
AMD Phenom QUAD 9950 Black Edition, 8GB

Senitel ::

Pa vidiš directional light? Verjetno ti directional povozi spotlight.

Tutankhamun ::

Ja sej je blo tko, da se je neki povozil. No zdej sm naredu sfero z odrezano kapco. Tko da lahk še not pogledam.

Ampak neki mi ne dela.
Če zgenerirram use točke za sfero.
1. pol pa še TriangleIndices povežem tako da se vidi vidi zunanjo plast sfere, je use ok.
2. Če pa dodam še TriangleIndices pa jih povežem mal drgač, da bi se vidla še notranja stran sfere, pa se neki grdo skvar.
Al kako bi lahko naredu, da bi se te trikotnički vidl z obeh strani?
AMD Phenom QUAD 9950 Black Edition, 8GB

Senitel ::

Najprej jih povežeš CCW, potem pa še CW? To bi moral delat, razen če si slučajno brez z-bufferja in je bil v prvem primeru slučaj, da je blo zaporedje renderiranja tako, da ti ni nič pokvarlo. Lahko narediš kak screenshot te grde stvari?

Tutankhamun ::

Ja sej tko sm naredu, pa ne dela.

 Vidi se samo zunanja stran

Vidi se samo zunanja stran



Pol sm jih pa še kontra povezu
 obe strani

obe strani



PA obe sferi sta enako obrnejni, da mata lukno na istem mestu na sliki. Sam na drugi se je ne vidi dobr. Js jo vrtim tuki, pa se bol vidi lukno.
Če pa narišem dve sferi ne celi eno iz notranje strani eno pa z zunanje pa zgleda ok

 ob strani pa dela

ob strani pa dela

AMD Phenom QUAD 9950 Black Edition, 8GB

Zgodovina sprememb…

Senitel ::

A lahko pokažeš še kodo? Tale obojestrana zgleda kot en šum...

Tutankhamun ::

Seveda lahko. Bom samo del ki shrani točke in poveže indice... Če pa rabš še ostalo bom pa še ostalo napisu.
void SphereCoordinates(float fi, float ro, float r, ref float x, ref float y, ref float z)
{
	float h = (float)(r * Math.Sin(fi * Math.PI / 180));
	y = (float)(r * Math.Cos(fi * Math.PI / 180));
	x = (float)(h * Math.Cos(ro * Math.P / 180));
	z = (float)(h * Math.Sin(ro * Math.PI / 180));
}


void DrawSphere ()
{
	const float _STEP = 1F;
	const float R = 10.0F;
	float x, y, z;
	x = y = z = 0;
	int i = 0;

	float ds = 25;

	Point3D p0, p1, p2, p3;

	for (float fi = 180; fi > ds; fi -= _STEP)
	{
		for (float ro = 360; ro > 0; ro -= _STEP)
		{
			SphereCoordinates(fi, ro, R, ref x, ref y, ref z);
			mesh.Positions.Add(p0 = new Point3D(x, y, z)); // 1
			SphereCoordinates(fi, ro - _STEP, R, ref x, ref y, ref z);
			mesh.Positions.Add(p1 = new Point3D(x, y, z)); // 2
			SphereCoordinates(fi - _STEP, ro, R, ref x, ref y, ref z);
			mesh.Positions.Add(p2 = new Point3D(x, y, z)); // 3
			SphereCoordinates(fi - _STEP, ro - _STEP, R, ref x, ref y, ref z);
			mesh.Positions.Add(p3 = new Point3D(x, y, z)); // 4

			// zunanja stran
			mesh.TriangleIndices.Add(i);
			mesh.TriangleIndices.Add(i + 1);
			mesh.TriangleIndices.Add(i + 2);

			mesh.TriangleIndices.Add(i + 2);
			mesh.TriangleIndices.Add(i + 1);
			mesh.TriangleIndices.Add(i + 3);
			
			// notranja stran
			mesh.TriangleIndices.Add(i + 2);
			mesh.TriangleIndices.Add(i + 1);
			mesh.TriangleIndices.Add(i);

			mesh.TriangleIndices.Add(i + 3);
			mesh.TriangleIndices.Add(i + 1);
			mesh.TriangleIndices.Add(i + 2);
			
			i += 4;
		}
	}
}


Točke pa tko računam:
 postopek

postopek

AMD Phenom QUAD 9950 Black Edition, 8GB

Senitel ::

Čak, normale daš zraven ali ne? Imaš med prvo in tretjo sliko tudi to bistveno razliko v generiranju vertexov?

Tutankhamun ::

Ne normal nimam. Zakaj so normale pomembne, zakaj se jih uporablja? Ker se mi nariše krogla brez normal sm pol naredu brez dodajanja normal.

NE. Najprej nardim koordinate za prvo kroglo, pa povežem indice da se vidi zunanja stran. Pol pa grem računat še koordinate druge krogle, ki je zamaknjena v y smer pa povežem indice da se vidi notranja stran. Lahko dam tut to kodo če te zanima.
AMD Phenom QUAD 9950 Black Edition, 8GB

Zgodovina sprememb…

Senitel ::

Normale NUJNO potrebuješ, da lahko lighting izračunaš. Glede na to, da ti dela brez sklepam, da jih MeshGeometry3D sam generira glede na trikotnike. To je problem, če imaš trikotnike podvojene z zamenjano orientacijo (prvi trikotnik kaže normala ven, drugi trikotnik normala kaže not in potem so normale samo numerične napake).
Če hočeš rezultat tak kot ga imaš na tretji sliki boš torej dejansko moral vse pozicije vstavit z zamenjano orientacijo (in obrnenimi normalami). Niti ni treba zamikat krogle po y.
Če nočeš lightinga na notranjem delu krogle, potem kreiraj normale, ki kažejo ven in daj not tako CCW kot CW trikotnike. Ker v primeru prve slike sedaj dobiš barvo ozadja, ker se po defaultu bo rasterizer zavračal CCW trikotnike.

Tutankhamun ::

Aha se pravi normale morjo bit. ok bom naredu.
Hvala za enkrat
AMD Phenom QUAD 9950 Black Edition, 8GB


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Izračun normale v C++ in povezava z Excelom

Oddelek: Programiranje
141517 (1167) primoz4p
»

[C#] Delo z okni - urejanje osebe

Oddelek: Programiranje
8915 (787) darkolord
»

Katero workstation graficno?

Oddelek: Kaj kupiti
191588 (1308) Senitel
»

Collision detection

Oddelek: Programiranje
81787 (1539) Senitel

Več podobnih tem